drm: allow commit/page_flip calls to *not* trigger an event

This commit is contained in:
Victor Brekenfeld 2021-04-25 23:36:15 +02:00
parent c8b370a030
commit 93edc842b2
3 changed files with 52 additions and 37 deletions

View File

@ -350,7 +350,7 @@ impl<A: AsRawFd + 'static> AtomicDrmSurface<A> {
*self.pending.read().unwrap() != *self.state.read().unwrap() *self.pending.read().unwrap() != *self.state.read().unwrap()
} }
pub fn commit(&self, framebuffer: framebuffer::Handle) -> Result<(), Error> { pub fn commit(&self, framebuffer: framebuffer::Handle, event: bool) -> Result<(), Error> {
if !self.active.load(Ordering::SeqCst) { if !self.active.load(Ordering::SeqCst) {
return Err(Error::DeviceInactive); return Err(Error::DeviceInactive);
} }
@ -430,14 +430,21 @@ impl<A: AsRawFd + 'static> AtomicDrmSurface<A> {
debug!(self.logger, "Setting screen: {:?}", req); debug!(self.logger, "Setting screen: {:?}", req);
let result = self.fd let result = self.fd
.atomic_commit( .atomic_commit(
&[ if event {
// on the atomic api we can modeset and trigger a page_flip event on the same call! &[
AtomicCommitFlags::PageFlipEvent, // on the atomic api we can modeset and trigger a page_flip event on the same call!
AtomicCommitFlags::AllowModeset, AtomicCommitFlags::PageFlipEvent,
// we also do not need to wait for completion, like with `set_crtc`. AtomicCommitFlags::AllowModeset,
// and have tested this already, so we do not expect any errors later down the line. // we also do not need to wait for completion, like with `set_crtc`.
AtomicCommitFlags::Nonblock, // and have tested this already, so we do not expect any errors later down the line.
], AtomicCommitFlags::Nonblock,
]
} else {
&[
AtomicCommitFlags::AllowModeset,
AtomicCommitFlags::Nonblock,
]
},
req, req,
) )
.map_err(|source| Error::Access { .map_err(|source| Error::Access {
@ -453,7 +460,7 @@ impl<A: AsRawFd + 'static> AtomicDrmSurface<A> {
result result
} }
pub fn page_flip(&self, framebuffer: framebuffer::Handle) -> Result<(), Error> { pub fn page_flip(&self, framebuffer: framebuffer::Handle, event: bool) -> Result<(), Error> {
if !self.active.load(Ordering::SeqCst) { if !self.active.load(Ordering::SeqCst) {
return Err(Error::DeviceInactive); return Err(Error::DeviceInactive);
} }
@ -473,7 +480,11 @@ impl<A: AsRawFd + 'static> AtomicDrmSurface<A> {
// indicating a problem in our assumptions. // indicating a problem in our assumptions.
trace!(self.logger, "Queueing page flip: {:?}", req); trace!(self.logger, "Queueing page flip: {:?}", req);
self.fd.atomic_commit( self.fd.atomic_commit(
&[AtomicCommitFlags::PageFlipEvent, AtomicCommitFlags::Nonblock], if event {
&[AtomicCommitFlags::PageFlipEvent, AtomicCommitFlags::Nonblock]
} else {
&[AtomicCommitFlags::Nonblock]
},
req, req,
) )
.map_err(|source| Error::Access { .map_err(|source| Error::Access {

View File

@ -202,7 +202,7 @@ impl<A: AsRawFd + 'static> LegacyDrmSurface<A> {
*self.pending.read().unwrap() != *self.state.read().unwrap() *self.pending.read().unwrap() != *self.state.read().unwrap()
} }
pub fn commit(&self, framebuffer: framebuffer::Handle) -> Result<(), Error> { pub fn commit(&self, framebuffer: framebuffer::Handle, event: bool) -> Result<(), Error> {
if !self.active.load(Ordering::SeqCst) { if !self.active.load(Ordering::SeqCst) {
return Err(Error::DeviceInactive); return Err(Error::DeviceInactive);
} }
@ -272,26 +272,30 @@ impl<A: AsRawFd + 'static> LegacyDrmSurface<A> {
*current = pending.clone(); *current = pending.clone();
// set crtc does not trigger page_flip events, so we immediately queue a flip if event {
// with the same framebuffer. // set crtc does not trigger page_flip events, so we immediately queue a flip
// this will result in wasting a frame, because this flip will need to wait // with the same framebuffer.
// for `set_crtc`, but is necessary to drive the event loop and thus provide // this will result in wasting a frame, because this flip will need to wait
// a more consistent api. // for `set_crtc`, but is necessary to drive the event loop and thus provide
ControlDevice::page_flip( // a more consistent api.
&*self.fd, ControlDevice::page_flip(
self.crtc, &*self.fd,
framebuffer, self.crtc,
&[PageFlipFlags::PageFlipEvent], framebuffer,
None, &[PageFlipFlags::PageFlipEvent],
) None,
.map_err(|source| Error::Access { )
errmsg: "Failed to queue page flip", .map_err(|source| Error::Access {
dev: self.fd.dev_path(), errmsg: "Failed to queue page flip",
source, dev: self.fd.dev_path(),
}) source,
})?;
}
Ok(())
} }
pub fn page_flip(&self, framebuffer: framebuffer::Handle) -> Result<(), Error> { pub fn page_flip(&self, framebuffer: framebuffer::Handle, event: bool) -> Result<(), Error> {
trace!(self.logger, "Queueing Page flip"); trace!(self.logger, "Queueing Page flip");
if !self.active.load(Ordering::SeqCst) { if !self.active.load(Ordering::SeqCst) {
@ -302,7 +306,7 @@ impl<A: AsRawFd + 'static> LegacyDrmSurface<A> {
&*self.fd, &*self.fd,
self.crtc, self.crtc,
framebuffer, framebuffer,
&[PageFlipFlags::PageFlipEvent], if event { &[PageFlipFlags::PageFlipEvent] } else { &[] },
None, None,
) )
.map_err(|source| Error::Access { .map_err(|source| Error::Access {

View File

@ -159,10 +159,10 @@ impl<A: AsRawFd + 'static> DrmSurface<A> {
/// but will trigger a `vblank` event once done. /// but will trigger a `vblank` event once done.
/// Make sure to [set a `DeviceHandler`](Device::set_handler) and /// Make sure to [set a `DeviceHandler`](Device::set_handler) and
/// [register the belonging `Device`](device_bind) before to receive the event in time. /// [register the belonging `Device`](device_bind) before to receive the event in time.
pub fn commit(&self, framebuffer: framebuffer::Handle) -> Result<(), Error> { pub fn commit(&self, framebuffer: framebuffer::Handle, event: bool) -> Result<(), Error> {
match &*self.internal { match &*self.internal {
DrmSurfaceInternal::Atomic(surf) => surf.commit(framebuffer), DrmSurfaceInternal::Atomic(surf) => surf.commit(framebuffer, event),
DrmSurfaceInternal::Legacy(surf) => surf.commit(framebuffer), DrmSurfaceInternal::Legacy(surf) => surf.commit(framebuffer, event),
} }
} }
@ -174,10 +174,10 @@ impl<A: AsRawFd + 'static> DrmSurface<A> {
/// This operation is not blocking and will produce a `vblank` event once swapping is done. /// This operation is not blocking and will produce a `vblank` event once swapping is done.
/// Make sure to [set a `DeviceHandler`](Device::set_handler) and /// Make sure to [set a `DeviceHandler`](Device::set_handler) and
/// [register the belonging `Device`](device_bind) before to receive the event in time. /// [register the belonging `Device`](device_bind) before to receive the event in time.
pub fn page_flip(&self, framebuffer: framebuffer::Handle) -> Result<(), Error> { pub fn page_flip(&self, framebuffer: framebuffer::Handle, event: bool) -> Result<(), Error> {
match &*self.internal { match &*self.internal {
DrmSurfaceInternal::Atomic(surf) => surf.page_flip(framebuffer), DrmSurfaceInternal::Atomic(surf) => surf.page_flip(framebuffer, event),
DrmSurfaceInternal::Legacy(surf) => surf.page_flip(framebuffer) DrmSurfaceInternal::Legacy(surf) => surf.page_flip(framebuffer, event),
} }
} }