Skip to content

Commit

Permalink
wayland: support wp-presentation version 2
Browse files Browse the repository at this point in the history
  • Loading branch information
cmeissl committed Nov 16, 2024
1 parent 86e7c3a commit b899004
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 19 deletions.
7 changes: 5 additions & 2 deletions anvil/src/udev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ use smithay::{
DrmLease, DrmLeaseBuilder, DrmLeaseHandler, DrmLeaseRequest, DrmLeaseState, LeaseRejected,
},
drm_syncobj::{supports_syncobj_eventfd, DrmSyncobjHandler, DrmSyncobjState},
presentation::Refresh,
},
};
use smithay_drm_extras::{
Expand Down Expand Up @@ -1292,8 +1293,10 @@ impl AnvilState<UdevData> {
clock,
output
.current_mode()
.map(|mode| Duration::from_secs_f64(1_000f64 / mode.refresh as f64))
.unwrap_or_default(),
.map(|mode| {
Refresh::fixed(Duration::from_secs_f64(1_000f64 / mode.refresh as f64))
})
.unwrap_or(Refresh::Unknown),
seq as u64,
flags,
);
Expand Down
7 changes: 5 additions & 2 deletions anvil/src/winit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ use smithay::{
dmabuf::{
DmabufFeedback, DmabufFeedbackBuilder, DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier,
},
presentation::Refresh,
},
};
use tracing::{error, info, warn};
Expand Down Expand Up @@ -399,8 +400,10 @@ pub fn run_winit() {
frame_target,
output
.current_mode()
.map(|mode| Duration::from_secs_f64(1_000f64 / mode.refresh as f64))
.unwrap_or_default(),
.map(|mode| {
Refresh::fixed(Duration::from_secs_f64(1_000f64 / mode.refresh as f64))
})
.unwrap_or(Refresh::Unknown),
0,
wp_presentation_feedback::Kind::Vsync,
)
Expand Down
7 changes: 5 additions & 2 deletions anvil/src/x11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ use smithay::{
dmabuf::{
DmabufFeedback, DmabufFeedbackBuilder, DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier,
},
presentation::Refresh,
},
};
use tracing::{error, info, trace, warn};
Expand Down Expand Up @@ -418,8 +419,10 @@ pub fn run_x11() {
frame_target,
output
.current_mode()
.map(|mode| Duration::from_secs_f64(1_000f64 / mode.refresh as f64))
.unwrap_or_default(),
.map(|mode| {
Refresh::fixed(Duration::from_secs_f64(1_000f64 / mode.refresh as f64))
})
.unwrap_or(Refresh::Unknown),
0,
wp_presentation_feedback::Kind::Vsync,
)
Expand Down
9 changes: 3 additions & 6 deletions src/desktop/wayland/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
wayland::{
compositor::{with_surface_tree_downward, SurfaceAttributes, SurfaceData, TraversalAction},
dmabuf::{DmabufFeedback, SurfaceDmabufFeedbackState},
presentation::{PresentationFeedbackCachedState, PresentationFeedbackCallback},
presentation::{PresentationFeedbackCachedState, PresentationFeedbackCallback, Refresh},
},
};
use std::{cell::RefCell, sync::Mutex, time::Duration};
Expand Down Expand Up @@ -339,13 +339,11 @@ impl SurfacePresentationFeedback {
output: &Output,
clk_id: u32,
time: impl Into<Duration>,
refresh: impl Into<Duration>,
refresh: Refresh,
seq: u64,
flags: wp_presentation_feedback::Kind,
) {
let time = time.into();
let refresh = refresh.into();

for callback in self.callbacks.drain(..) {
if callback.clk_id() == clk_id {
callback.presented(output, time, refresh, seq, flags | self.flags)
Expand Down Expand Up @@ -401,15 +399,14 @@ impl OutputPresentationFeedback {
pub fn presented<T, Kind>(
&mut self,
time: T,
refresh: impl Into<Duration>,
refresh: Refresh,
seq: u64,
flags: wp_presentation_feedback::Kind,
) where
T: Into<Time<Kind>>,
Kind: crate::utils::NonNegativeClockSource,
{
let time = time.into();
let refresh = refresh.into();
let clk_id = Kind::ID as u32;
if let Some(output) = self.output.upgrade() {
for mut callback in self.callbacks.drain(..) {
Expand Down
52 changes: 45 additions & 7 deletions src/wayland/presentation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
//! # use smithay::{output::{Output, PhysicalProperties, Subpixel}, wayland::compositor::with_states};
//! # use wayland_server::{backend::ObjectId, protocol::wl_surface::WlSurface, Resource};
//! # use std::time::Duration;
//! use smithay::wayland::presentation::PresentationFeedbackCachedState;
//! use smithay::wayland::presentation::{PresentationFeedbackCachedState, Refresh};
//! use wayland_protocols::wp::presentation_time::server::wp_presentation_feedback;
//!
//! # struct State;
Expand All @@ -63,7 +63,7 @@
//! // ... send frame callbacks and present frame
//!
//! # let time = Duration::ZERO;
//! # let refresh = Duration::from_secs_f64(1_000f64 / 60_000f64);
//! # let refresh = Refresh::fixed(Duration::from_secs_f64(1_000f64 / 60_000f64));
//! # let seq = 0;
//! for feedback in presentation_feedbacks {
//! feedback.presented(&output, time, refresh, seq, wp_presentation_feedback::Kind::Vsync);
Expand All @@ -81,6 +81,8 @@ use crate::output::Output;

use super::compositor::{with_states, Cacheable};

const EVT_PRESENTED_VARIABLE_SINCE: u32 = 2;

/// State of the wp_presentation global
#[derive(Debug)]
pub struct PresentationState {
Expand All @@ -100,7 +102,7 @@ impl PresentationState {
+ 'static,
{
PresentationState {
global: display.create_global::<D, wp_presentation::WpPresentation, u32>(1, clk_id),
global: display.create_global::<D, wp_presentation::WpPresentation, u32>(2, clk_id),
}
}

Expand Down Expand Up @@ -154,7 +156,7 @@ where
.cached_state
.get::<PresentationFeedbackCachedState>()
.pending()
.add_callback(surface.clone(), *data, callback);
.add_callback(&surface, *data, callback);
});
}
wp_presentation::Request::Destroy => {
Expand Down Expand Up @@ -196,6 +198,31 @@ pub struct PresentationFeedbackCallback {
callback: wp_presentation_feedback::WpPresentationFeedback,
}

/// Refresh of the output on which the surface was presented
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Refresh {
/// The output does not have a known refresh rate
Unknown,
/// The output has a variable refresh rate
///
/// The passed refresh rate has to correspond to the minimum (fastest) rate
Variable(Duration),
/// The output has a fixed rate
Fixed(Duration),
}

impl Refresh {
/// Construct a [`Refresh::Variable`] from a [`Duration`]
pub fn variable(min: impl Into<Duration>) -> Self {
Self::Variable(min.into())
}

/// Construct a [`Refresh::Fixed`] from a [`Duration`]
pub fn fixed(rate: impl Into<Duration>) -> Self {
Self::Fixed(rate.into())
}
}

impl PresentationFeedbackCallback {
/// Get the id of the clock that was used at bind
pub fn clk_id(&self) -> u32 {
Expand All @@ -207,7 +234,7 @@ impl PresentationFeedbackCallback {
self,
output: &Output,
time: impl Into<Duration>,
refresh: impl Into<Duration>,
refresh: Refresh,
seq: u64,
flags: wp_presentation_feedback::Kind,
) {
Expand All @@ -233,11 +260,22 @@ impl PresentationFeedbackCallback {
self.callback.sync_output(&output);
}

// Since version 2 wp_presentation supports variable refresh rates,
// in which case the minimum (fastest rate) refresh is sent.
// Clients binding an earlier version shall receive a zero refresh in this case.
let refresh = match refresh {
Refresh::Fixed(duration) => duration,
Refresh::Variable(duration) if self.callback.version() >= EVT_PRESENTED_VARIABLE_SINCE => {
duration
}
_ => Duration::ZERO,
};

let time = time.into();
let tv_sec_hi = (time.as_secs() >> 32) as u32;
let tv_sec_lo = (time.as_secs() & 0xFFFFFFFF) as u32;
let tv_nsec = time.subsec_nanos();
let refresh = refresh.into().as_nanos() as u32;
let refresh = refresh.as_nanos() as u32;
let seq_hi = (seq >> 32) as u32;
let seq_lo = (seq & 0xFFFFFFFF) as u32;

Expand All @@ -262,7 +300,7 @@ pub struct PresentationFeedbackCachedState {
impl PresentationFeedbackCachedState {
fn add_callback(
&mut self,
surface: wl_surface::WlSurface,
surface: &wl_surface::WlSurface,
clk_id: u32,
callback: wp_presentation_feedback::WpPresentationFeedback,
) {
Expand Down

0 comments on commit b899004

Please sign in to comment.