output-configuration: Support cosmic-ext v2
This commit is contained in:
parent
80965a61b9
commit
81b9fb179b
9 changed files with 120 additions and 25 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue