output-configuration: Support cosmic-ext v2

This commit is contained in:
Victoria Brekenfeld 2024-11-18 21:30:02 +01:00 committed by Victoria Brekenfeld
parent 80965a61b9
commit 81b9fb179b
9 changed files with 120 additions and 25 deletions

12
Cargo.lock generated
View file

@ -899,7 +899,7 @@ dependencies = [
[[package]]
name = "cosmic-protocols"
version = "0.1.0"
source = "git+https://github.com/pop-os/cosmic-protocols?branch=main#ec1616b90fa6b4568709cfe2c0627b1e8cc887e0"
source = "git+https://github.com/pop-os/cosmic-protocols?branch=main#27d70b6eb9c785a2a48341016f32a7b1ac4980ac"
dependencies = [
"bitflags 2.6.0",
"wayland-backend",
@ -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]]
@ -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]]
@ -5879,7 +5879,7 @@ dependencies = [
"js-sys",
"khronos-egl",
"libc",
"libloading 0.8.5",
"libloading 0.7.4",
"log",
"metal",
"naga",

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-only
use crate::{
config::{OutputConfig, OutputState},
config::{AdaptiveSync, OutputConfig, OutputState},
shell::Shell,
utils::prelude::*,
};
@ -664,6 +664,10 @@ fn populate_modes(
max_bpc,
scale,
transform,
// Try opportunistic VRR by default,
// if not supported this will be turned off on `resume`,
// when we have the `Surface` to actually check for support.
vrr: AdaptiveSync::Enabled,
..std::mem::take(&mut *output_config)
};

View file

@ -684,6 +684,9 @@ impl KmsState {
match surface.resume(drm_surface, gbm, cursor_size) {
Ok(_) => {
surface.output.set_adaptive_sync_support(
surface.adaptive_sync_support().ok(),
);
if surface.use_adaptive_sync(vrr)? {
surface.output.set_adaptive_sync(vrr);
} else {

View file

@ -405,6 +405,14 @@ impl Surface {
rx.recv().context("Surface thread died")?
}
pub fn adaptive_sync_support(&self) -> Result<VrrSupport> {
let (tx, rx) = std::sync::mpsc::sync_channel(1);
let _ = self
.thread_command
.send(ThreadCommand::AdaptiveSyncAvailable(tx));
rx.recv().context("Surface thread died")?
}
pub fn use_adaptive_sync(&mut self, vrr: AdaptiveSync) -> Result<bool> {
if vrr != AdaptiveSync::Disabled {
let (tx, rx) = std::sync::mpsc::sync_channel(1);

View file

@ -1,4 +1,5 @@
use smithay::{
backend::drm::VrrSupport as Support,
output::{Output, WeakOutput},
utils::{Rectangle, Transform},
};
@ -21,6 +22,8 @@ pub trait OutputExt {
fn geometry(&self) -> Rectangle<i32, Global>;
fn adaptive_sync(&self) -> AdaptiveSync;
fn set_adaptive_sync(&self, vrr: AdaptiveSync);
fn adaptive_sync_support(&self) -> Option<Support>;
fn set_adaptive_sync_support(&self, vrr: Option<Support>);
fn mirroring(&self) -> Option<Output>;
fn set_mirroring(&self, output: Option<Output>);
@ -30,7 +33,7 @@ pub trait OutputExt {
}
struct Vrr(AtomicU8);
struct VrrSupport(AtomicU8);
struct Mirroring(Mutex<Option<WeakOutput>>);
impl OutputExt for Output {
@ -72,6 +75,32 @@ impl OutputExt for Output {
);
}
fn adaptive_sync_support(&self) -> Option<Support> {
self.user_data()
.get::<VrrSupport>()
.map(|vrr| match vrr.0.load(Ordering::SeqCst) {
0 => None,
2 => Some(Support::RequiresModeset),
3 => Some(Support::Supported),
_ => Some(Support::NotSupported),
})
.flatten()
}
fn set_adaptive_sync_support(&self, vrr: Option<Support>) {
let user_data = self.user_data();
user_data.insert_if_missing_threadsafe(|| VrrSupport(AtomicU8::new(0)));
user_data.get::<VrrSupport>().unwrap().0.store(
match vrr {
None => 0,
Some(Support::NotSupported) => 1,
Some(Support::RequiresModeset) => 2,
Some(Support::Supported) => 3,
},
Ordering::SeqCst,
);
}
fn mirroring(&self) -> Option<Output> {
self.user_data().get::<Mirroring>().and_then(|mirroring| {
mirroring

View file

@ -4,7 +4,7 @@ use smithay::{output::Output, utils::Point};
use tracing::{error, warn};
use crate::{
config::{AdaptiveSync, OutputConfig, OutputState},
config::{OutputConfig, OutputState},
state::State,
wayland::protocols::output_configuration::{
delegate_output_configuration, ModeConfiguration, OutputConfiguration,
@ -120,11 +120,7 @@ impl State {
current_config.position = (position.x as u32, position.y as u32);
}
if let Some(vrr) = adaptive_sync {
current_config.vrr = if *vrr {
AdaptiveSync::Force
} else {
AdaptiveSync::Disabled
};
current_config.vrr = *vrr;
}
if let Some(mirror) = mirroring {
current_config.enabled = OutputState::Mirroring(mirror.name());

View file

@ -270,6 +270,29 @@ where
}
}
}
zcosmic_output_configuration_head_v1::Request::SetAdaptiveSyncExt { state } => {
if let Ok(obj) = obj.upgrade() {
if let Some(data) = obj.data::<PendingOutputConfiguration>() {
let mut pending = data.lock().unwrap();
if pending.adaptive_sync.is_some() {
obj.post_error(
zwlr_output_configuration_head_v1::Error::AlreadySet,
format!("{:?} already had an adaptive_sync state configured", obj),
);
return;
}
pending.adaptive_sync = match state.into_result() {
Ok(zcosmic_output_head_v1::AdaptiveSyncStateExt::Always) => {
Some(AdaptiveSync::Force)
}
Ok(zcosmic_output_head_v1::AdaptiveSyncStateExt::Automatic) => {
Some(AdaptiveSync::Enabled)
}
_ => Some(AdaptiveSync::Disabled),
};
}
}
}
_ => {}
}
}

View file

@ -481,8 +481,8 @@ where
}
pending.adaptive_sync = Some(match state.into_result() {
Ok(state) => match state {
zwlr_output_head_v1::AdaptiveSyncState::Enabled => true,
_ => false,
zwlr_output_head_v1::AdaptiveSyncState::Enabled => AdaptiveSync::Force,
_ => AdaptiveSync::Disabled,
},
Err(err) => {
obj.post_error(

View file

@ -3,9 +3,11 @@
use cosmic_protocols::output_management::v1::server::{
zcosmic_output_configuration_head_v1::ZcosmicOutputConfigurationHeadV1,
zcosmic_output_configuration_v1::ZcosmicOutputConfigurationV1,
zcosmic_output_head_v1::ZcosmicOutputHeadV1, zcosmic_output_manager_v1::ZcosmicOutputManagerV1,
zcosmic_output_head_v1::{self, ZcosmicOutputHeadV1},
zcosmic_output_manager_v1::ZcosmicOutputManagerV1,
};
use smithay::{
backend::drm::VrrSupport,
output::{Mode, Output, WeakOutput},
reexports::{
wayland_protocols_wlr::output_management::v1::server::{
@ -98,7 +100,7 @@ pub struct PendingOutputConfigurationInner {
position: Option<Point<i32, Logical>>,
transform: Option<Transform>,
scale: Option<f64>,
adaptive_sync: Option<bool>,
adaptive_sync: Option<AdaptiveSync>,
}
pub type PendingOutputConfiguration = Mutex<PendingOutputConfigurationInner>;
@ -110,7 +112,7 @@ pub enum OutputConfiguration {
position: Option<Point<i32, Logical>>,
transform: Option<Transform>,
scale: Option<f64>,
adaptive_sync: Option<bool>,
adaptive_sync: Option<AdaptiveSync>,
},
Disabled,
}
@ -178,7 +180,7 @@ where
);
let extension_global = dh.create_global::<D, ZcosmicOutputManagerV1, _>(
1,
2,
OutputMngrGlobalData {
filter: Box::new(client_filter),
},
@ -434,11 +436,6 @@ where
let scale = output.current_scale().fractional_scale();
instance.obj.scale(scale);
if let Some(extension_obj) = instance.extension_obj.as_ref() {
extension_obj.scale_1000((scale * 1000.0).round() as i32);
extension_obj.mirroring(output.mirroring().map(|o| o.name()));
}
if instance.obj.version() >= zwlr_output_head_v1::EVT_ADAPTIVE_SYNC_SINCE {
instance
@ -449,6 +446,41 @@ where
zwlr_output_head_v1::AdaptiveSyncState::Enabled
});
}
if let Some(extension_obj) = instance.extension_obj.as_ref() {
extension_obj.scale_1000((scale * 1000.0).round() as i32);
extension_obj.mirroring(output.mirroring().map(|o| o.name()));
if extension_obj.version() >= zcosmic_output_head_v1::EVT_ADAPTIVE_SYNC_EXT_SINCE {
extension_obj.adaptive_sync_ext(match output.adaptive_sync() {
AdaptiveSync::Disabled => {
zcosmic_output_head_v1::AdaptiveSyncStateExt::Disabled
}
AdaptiveSync::Enabled => {
zcosmic_output_head_v1::AdaptiveSyncStateExt::Automatic
}
AdaptiveSync::Force => zcosmic_output_head_v1::AdaptiveSyncStateExt::Always,
});
extension_obj.adaptive_sync_available(
match output
.adaptive_sync_support()
.unwrap_or(VrrSupport::NotSupported)
{
VrrSupport::NotSupported => {
zcosmic_output_head_v1::AdaptiveSyncAvailability::Unsupported
}
VrrSupport::RequiresModeset => {
zcosmic_output_head_v1::AdaptiveSyncAvailability::RequiresModeset
}
VrrSupport::Supported => {
zcosmic_output_head_v1::AdaptiveSyncAvailability::Supported
}
},
);
}
}
}
if instance.obj.version() >= zwlr_output_head_v1::EVT_MAKE_SINCE {