drm: Use EventMetadata to pass on frame timings
This commit is contained in:
parent
ab89bda503
commit
20051d384d
|
@ -122,7 +122,7 @@ fn main() {
|
||||||
let mut event_loop = EventLoop::<()>::try_new().unwrap();
|
let mut event_loop = EventLoop::<()>::try_new().unwrap();
|
||||||
event_loop
|
event_loop
|
||||||
.handle()
|
.handle()
|
||||||
.insert_source(device, move |event, _: &mut (), _: &mut ()| match event {
|
.insert_source(device, move |event, _: &mut _, _: &mut ()| match event {
|
||||||
DrmEvent::VBlank(crtc) => vblank_handler.vblank(crtc),
|
DrmEvent::VBlank(crtc) => vblank_handler.vblank(crtc),
|
||||||
DrmEvent::Error(e) => panic!("{}", e),
|
DrmEvent::Error(e) => panic!("{}", e),
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,10 +3,11 @@ use std::cell::RefCell;
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::{atomic::AtomicBool, Arc};
|
use std::sync::{atomic::AtomicBool, Arc};
|
||||||
|
use std::time::{Instant, SystemTime};
|
||||||
|
|
||||||
use calloop::{EventSource, Interest, Poll, PostAction, Readiness, Token, TokenFactory};
|
use calloop::{EventSource, Interest, Poll, PostAction, Readiness, Token, TokenFactory};
|
||||||
use drm::control::{connector, crtc, Device as ControlDevice, Event, Mode, ResourceHandles};
|
use drm::control::{connector, crtc, Device as ControlDevice, Event, Mode, ResourceHandles};
|
||||||
use drm::{ClientCapability, Device as BasicDevice};
|
use drm::{ClientCapability, Device as BasicDevice, DriverCapability};
|
||||||
use nix::libc::dev_t;
|
use nix::libc::dev_t;
|
||||||
use nix::sys::stat::fstat;
|
use nix::sys::stat::fstat;
|
||||||
|
|
||||||
|
@ -27,6 +28,7 @@ pub struct DrmDevice<A: AsRawFd + 'static> {
|
||||||
#[cfg(feature = "backend_session")]
|
#[cfg(feature = "backend_session")]
|
||||||
pub(super) links: RefCell<Vec<crate::utils::signaling::SignalToken>>,
|
pub(super) links: RefCell<Vec<crate::utils::signaling::SignalToken>>,
|
||||||
has_universal_planes: bool,
|
has_universal_planes: bool,
|
||||||
|
has_monotonic_timestamps: bool,
|
||||||
resources: ResourceHandles,
|
resources: ResourceHandles,
|
||||||
pub(super) logger: ::slog::Logger,
|
pub(super) logger: ::slog::Logger,
|
||||||
token: Token,
|
token: Token,
|
||||||
|
@ -136,6 +138,10 @@ impl<A: AsRawFd + 'static> DrmDevice<A> {
|
||||||
let has_universal_planes = dev
|
let has_universal_planes = dev
|
||||||
.set_client_capability(ClientCapability::UniversalPlanes, true)
|
.set_client_capability(ClientCapability::UniversalPlanes, true)
|
||||||
.is_ok();
|
.is_ok();
|
||||||
|
let has_monotonic_timestamps = dev
|
||||||
|
.get_driver_capability(DriverCapability::MonotonicTimestamp)
|
||||||
|
.unwrap_or(0)
|
||||||
|
== 1;
|
||||||
let resources = dev.resource_handles().map_err(|source| Error::Access {
|
let resources = dev.resource_handles().map_err(|source| Error::Access {
|
||||||
errmsg: "Error loading resource handles",
|
errmsg: "Error loading resource handles",
|
||||||
dev: dev.dev_path(),
|
dev: dev.dev_path(),
|
||||||
|
@ -154,6 +160,7 @@ impl<A: AsRawFd + 'static> DrmDevice<A> {
|
||||||
#[cfg(feature = "backend_session")]
|
#[cfg(feature = "backend_session")]
|
||||||
links: RefCell::new(Vec::new()),
|
links: RefCell::new(Vec::new()),
|
||||||
has_universal_planes,
|
has_universal_planes,
|
||||||
|
has_monotonic_timestamps,
|
||||||
resources,
|
resources,
|
||||||
logger: log,
|
logger: log,
|
||||||
token: Token::invalid(),
|
token: Token::invalid(),
|
||||||
|
@ -311,12 +318,30 @@ pub enum DrmEvent {
|
||||||
Error(Error),
|
Error(Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Timing metadata for page-flip events
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct EventMetadata {
|
||||||
|
/// The time the frame flip happend
|
||||||
|
pub time: Time,
|
||||||
|
/// The sequence number of the frame
|
||||||
|
pub sequence: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Either a realtime or monotonic timestamp
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Time {
|
||||||
|
/// Monotonic time stamp
|
||||||
|
Monotonic(Instant),
|
||||||
|
/// Realtime time stamp
|
||||||
|
Realtime(SystemTime),
|
||||||
|
}
|
||||||
|
|
||||||
impl<A> EventSource for DrmDevice<A>
|
impl<A> EventSource for DrmDevice<A>
|
||||||
where
|
where
|
||||||
A: AsRawFd + 'static,
|
A: AsRawFd + 'static,
|
||||||
{
|
{
|
||||||
type Event = DrmEvent;
|
type Event = DrmEvent;
|
||||||
type Metadata = ();
|
type Metadata = Option<EventMetadata>;
|
||||||
type Ret = ();
|
type Ret = ();
|
||||||
|
|
||||||
fn process_events<F>(
|
fn process_events<F>(
|
||||||
|
@ -336,7 +361,22 @@ where
|
||||||
for event in events {
|
for event in events {
|
||||||
if let Event::PageFlip(event) = event {
|
if let Event::PageFlip(event) = event {
|
||||||
trace!(self.logger, "Got a page-flip event for crtc ({:?})", event.crtc);
|
trace!(self.logger, "Got a page-flip event for crtc ({:?})", event.crtc);
|
||||||
callback(DrmEvent::VBlank(event.crtc), &mut ());
|
let metadata = EventMetadata {
|
||||||
|
time: if self.has_monotonic_timestamps {
|
||||||
|
// There is no way to create an Instant, although the underlying type on unix systems
|
||||||
|
// is just libc::timespec, which is literally what drm-rs is getting from the kernel and just converting
|
||||||
|
// into a Duration. So we cheat and initialize a Zero-Instant (because although Instant::ZERO
|
||||||
|
// exists, its private, so you cannot create abitrary Instants). What we really need is a unix-Ext
|
||||||
|
// trait for both SystemTime and Instant to convert from a libc::timespec.
|
||||||
|
//
|
||||||
|
// But this works for now, although it is quite the hack.
|
||||||
|
Time::Monotonic(unsafe { std::mem::zeroed::<Instant>() } + event.duration)
|
||||||
|
} else {
|
||||||
|
Time::Realtime(SystemTime::UNIX_EPOCH + event.duration)
|
||||||
|
},
|
||||||
|
sequence: event.frame,
|
||||||
|
};
|
||||||
|
callback(DrmEvent::VBlank(event.crtc), &mut Some(metadata));
|
||||||
} else {
|
} else {
|
||||||
trace!(
|
trace!(
|
||||||
self.logger,
|
self.logger,
|
||||||
|
@ -353,7 +393,7 @@ where
|
||||||
dev: self.dev_path(),
|
dev: self.dev_path(),
|
||||||
source,
|
source,
|
||||||
}),
|
}),
|
||||||
&mut (),
|
&mut None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ pub mod node;
|
||||||
pub(self) mod session;
|
pub(self) mod session;
|
||||||
pub(self) mod surface;
|
pub(self) mod surface;
|
||||||
|
|
||||||
pub use device::{DevPath, DrmDevice, DrmEvent};
|
pub use device::{DevPath, DrmDevice, DrmEvent, EventMetadata as DrmEventMetadata, Time as DrmEventTime};
|
||||||
pub use error::Error as DrmError;
|
pub use error::Error as DrmError;
|
||||||
pub use node::{CreateDrmNodeError, DrmNode, NodeType};
|
pub use node::{CreateDrmNodeError, DrmNode, NodeType};
|
||||||
#[cfg(feature = "backend_gbm")]
|
#[cfg(feature = "backend_gbm")]
|
||||||
|
|
Loading…
Reference in New Issue