Skip to content

Commit

Permalink
wp-presentation: implement version 2
Browse files Browse the repository at this point in the history
  • Loading branch information
mahkoh committed Sep 25, 2024
1 parent fb2e0f7 commit e4e30a2
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 20 deletions.
39 changes: 32 additions & 7 deletions src/backends/metal/video.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ use {
MetalBackend, MetalError,
},
drm_feedback::DrmFeedback,
edid::Descriptor,
edid::{CtaDataBlock, Descriptor, EdidExtension},
format::{Format, ARGB8888, XRGB8888},
gfx_api::{
needs_render_usage, AcquireSync, GfxContext, GfxFramebuffer, GfxTexture, ReleaseSync,
SyncFile,
},
ifs::{
wl_output::OutputId,
wp_presentation_feedback::{KIND_HW_COMPLETION, KIND_VSYNC, KIND_ZERO_COPY},
wp_presentation_feedback::{KIND_HW_COMPLETION, KIND_VRR, KIND_VSYNC, KIND_ZERO_COPY},
},
state::State,
tree::OutputNode,
Expand Down Expand Up @@ -331,6 +331,7 @@ pub struct ConnectorDisplayData {
pub non_desktop: bool,
pub non_desktop_effective: bool,
pub vrr_capable: bool,
pub vrr_refresh_max_nsec: u64,

pub connector_id: ConnectorKernelId,
pub output_id: Rc<OutputId>,
Expand Down Expand Up @@ -1117,6 +1118,7 @@ fn create_connector_display_data(
let mut name = String::new();
let mut manufacturer = String::new();
let mut serial_number = String::new();
let mut vrr_refresh_max_nsec = u64::MAX;
let connector_id = ConnectorKernelId {
ty: ConnectorType::from_drm(info.connector_type),
idx: info.connector_type_id,
Expand Down Expand Up @@ -1182,6 +1184,28 @@ fn create_connector_display_data(
);
serial_number = edid.base_block.id_serial_number.to_string();
}
let min_vrr_hz = 'fetch_min_hz: {
for ext in &edid.extension_blocks {
if let EdidExtension::CtaV3(cta) = ext {
for data_block in &cta.data_blocks {
if let CtaDataBlock::VendorAmd(amd) = data_block {
break 'fetch_min_hz amd.minimum_refresh_hz as u64;
}
}
}
}
for desc in &edid.base_block.descriptors {
if let Some(desc) = desc {
if let Descriptor::DisplayRangeLimitsAndAdditionalTiming(timings) = desc {
break 'fetch_min_hz timings.vertical_field_rate_min as u64;
}
}
}
0
};
if min_vrr_hz > 0 {
vrr_refresh_max_nsec = 1_000_000_000 / min_vrr_hz;
}
}
let output_id = Rc::new(OutputId::new(
connector_id.to_string(),
Expand Down Expand Up @@ -1237,6 +1261,7 @@ fn create_connector_display_data(
non_desktop,
non_desktop_effective: non_desktop_override.unwrap_or(non_desktop),
vrr_capable,
vrr_refresh_max_nsec,
connection,
mm_width: info.mm_width,
mm_height: info.mm_height,
Expand Down Expand Up @@ -1987,17 +2012,17 @@ impl MetalBackend {
if connector.presentation_is_zero_copy.get() {
flags |= KIND_ZERO_COPY;
}
let refresh = match crtc.vrr_enabled.value.get() {
true => 0,
false => dd.refresh,
};
if crtc.vrr_enabled.value.get() {
flags |= KIND_VRR;
}
if let Some(g) = &global {
g.presented(
tv_sec as _,
tv_usec * 1000,
refresh,
dd.refresh,
connector.sequence.get(),
flags,
dd.vrr_refresh_max_nsec,
);
}
}
Expand Down
6 changes: 1 addition & 5 deletions src/edid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1161,32 +1161,28 @@ pub struct EdidBaseBlock {
#[derive(Debug)]
pub enum EdidExtension {
Unknown,
#[expect(dead_code)]
CtaV3(CtaExtensionV3),
}

#[derive(Debug)]
pub struct CtaExtensionV3 {
#[expect(dead_code)]
pub data_blocks: Vec<CtaDataBlock>,
}

#[derive(Debug)]
pub enum CtaDataBlock {
Unknown,
#[expect(dead_code)]
VendorAmd(CtaAmdVendorDataBlock),
}

#[derive(Debug)]
#[expect(dead_code)]
pub struct CtaAmdVendorDataBlock {
pub minimum_refresh_hz: u8,
#[expect(dead_code)]
pub maximum_refresh_hz: u8,
}

#[derive(Debug)]
#[expect(dead_code)]
pub struct EdidFile {
pub base_block: EdidBaseBlock,
pub extension_blocks: Vec<EdidExtension>,
Expand Down
22 changes: 17 additions & 5 deletions src/ifs/wl_surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ use {
zwlr_layer_surface_v1::{PendingLayerSurfaceData, ZwlrLayerSurfaceV1Error},
},
wp_content_type_v1::ContentType,
wp_presentation_feedback::WpPresentationFeedback,
wp_presentation_feedback::{WpPresentationFeedback, KIND_VRR, VRR_BOUNDS_SINCE},
zwp_linux_dmabuf_feedback_v1::ZwpLinuxDmabufFeedbackV1,
},
leaks::Tracker,
Expand All @@ -68,10 +68,10 @@ use {
VblankListener,
},
utils::{
cell_ext::CellExt, clonecell::CloneCell, copyhashmap::CopyHashMap,
double_buffered::DoubleBuffered, errorfmt::ErrorFmt, event_listener::EventListener,
linkedlist::LinkedList, numcell::NumCell, smallmap::SmallMap,
transform_ext::TransformExt,
bitflags::BitflagsExt, cell_ext::CellExt, clonecell::CloneCell,
copyhashmap::CopyHashMap, double_buffered::DoubleBuffered, errorfmt::ErrorFmt,
event_listener::EventListener, linkedlist::LinkedList, numcell::NumCell,
smallmap::SmallMap, transform_ext::TransformExt,
},
video::{
dmabuf::DMA_BUF_SYNC_READ,
Expand Down Expand Up @@ -2096,15 +2096,27 @@ impl PresentationListener for WlSurface {
refresh: u32,
seq: u64,
flags: u32,
vrr_refresh_max_nsec: u64,
) {
let bindings = output.global.bindings.borrow();
let bindings = bindings.get(&self.client.id);
let vrr_refresh_min_nsec = refresh as u64;
for pf in self.latched_presentation_feedback.borrow_mut().drain(..) {
if let Some(bindings) = bindings {
for binding in bindings.values() {
pf.send_sync_output(binding);
}
}
let mut flags = flags;
let mut refresh = refresh;
if flags.contains(KIND_VRR) {
if pf.version >= VRR_BOUNDS_SINCE {
pf.send_variable_refresh_bounds(vrr_refresh_min_nsec, vrr_refresh_max_nsec);
} else {
flags &= !KIND_VRR;
refresh = 0;
}
}
pf.send_presented(tv_sec, tv_nsec, refresh, seq, flags);
let _ = pf.client.remove_obj(&*pf);
}
Expand Down
2 changes: 1 addition & 1 deletion src/ifs/wp_presentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl Global for WpPresentationGlobal {
}

fn version(&self) -> u32 {
1
2
}
}

Expand Down
13 changes: 13 additions & 0 deletions src/ifs/wp_presentation_feedback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ pub const KIND_VSYNC: u32 = 0x1;
pub const KIND_HW_CLOCK: u32 = 0x2;
pub const KIND_HW_COMPLETION: u32 = 0x4;
pub const KIND_ZERO_COPY: u32 = 0x8;
pub const KIND_VRR: u32 = 0x10;

pub const VRR_BOUNDS_SINCE: Version = Version(2);

impl WpPresentationFeedback {
pub fn send_sync_output(&self, output: &WlOutput) {
Expand All @@ -32,6 +35,16 @@ impl WpPresentationFeedback {
});
}

pub fn send_variable_refresh_bounds(&self, min_nsec: u64, max_nsec: u64) {
self.client.event(VariableRefreshBounds {
self_id: self.id,
refresh_min_nsec_hi: (min_nsec >> 32) as u32,
refresh_min_nsec_lo: min_nsec as u32,
refresh_max_nsec_hi: (max_nsec >> 32) as u32,
refresh_max_nsec_lo: max_nsec as u32,
});
}

pub fn send_presented(&self, tv_sec: u64, tv_nsec: u32, refresh: u32, seq: u64, flags: u32) {
self.client.event(Presented {
self_id: self.id,
Expand Down
21 changes: 19 additions & 2 deletions src/tree/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ pub trait PresentationListener {
refresh: u32,
seq: u64,
flags: u32,
vrr_refresh_max_nsec: u64,
);
}

Expand Down Expand Up @@ -138,9 +139,25 @@ impl OutputNode {
}
}

pub fn presented(&self, tv_sec: u64, tv_nsec: u32, refresh: u32, seq: u64, flags: u32) {
pub fn presented(
&self,
tv_sec: u64,
tv_nsec: u32,
refresh: u32,
seq: u64,
flags: u32,
vrr_refresh_max_nsec: u64,
) {
for listener in self.presentation_event.iter() {
listener.presented(self, tv_sec, tv_nsec, refresh, seq, flags);
listener.presented(
self,
tv_sec,
tv_nsec,
refresh,
seq,
flags,
vrr_refresh_max_nsec,
);
}
}

Expand Down
7 changes: 7 additions & 0 deletions wire/wp_presentation_feedback.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,10 @@ event presented {
event discarded {

}

event variable_refresh_bounds (since = 2) {
refresh_min_nsec_hi: u32,
refresh_min_nsec_lo: u32,
refresh_max_nsec_hi: u32,
refresh_max_nsec_lo: u32,
}

0 comments on commit e4e30a2

Please sign in to comment.