wl_surface: handle explicit sync release automatically
This commit is contained in:
parent
8f576f498e
commit
382c0b6c71
3 changed files with 64 additions and 63 deletions
|
|
@ -76,6 +76,7 @@ use {
|
||||||
object::{Object, Version},
|
object::{Object, Version},
|
||||||
rect::{DamageQueue, Rect, Region},
|
rect::{DamageQueue, Rect, Region},
|
||||||
renderer::Renderer,
|
renderer::Renderer,
|
||||||
|
state::State,
|
||||||
tree::{
|
tree::{
|
||||||
BeforeLatchListener, BeforeLatchResult, ContainerNode, FindTreeResult, FoundNode,
|
BeforeLatchListener, BeforeLatchResult, ContainerNode, FindTreeResult, FoundNode,
|
||||||
LatchListener, Node, NodeId, NodeLayerLink, NodeLocation, NodeVisitor, NodeVisitorBase,
|
LatchListener, Node, NodeId, NodeLayerLink, NodeLocation, NodeVisitor, NodeVisitorBase,
|
||||||
|
|
@ -99,6 +100,7 @@ use {
|
||||||
},
|
},
|
||||||
ahash::AHashMap,
|
ahash::AHashMap,
|
||||||
isnt::std_1::{primitive::IsntSliceExt, vec::IsntVecExt},
|
isnt::std_1::{primitive::IsntSliceExt, vec::IsntVecExt},
|
||||||
|
smallvec::SmallVec,
|
||||||
std::{
|
std::{
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
collections::hash_map::{Entry, OccupiedEntry},
|
collections::hash_map::{Entry, OccupiedEntry},
|
||||||
|
|
@ -211,46 +213,18 @@ impl NodeVisitorBase for SurfaceSendPreferredColorDescription {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SurfaceBufferExplicitRelease {
|
|
||||||
sync_obj: Rc<SyncObj>,
|
|
||||||
point: SyncObjPoint,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SurfaceBuffer {
|
pub struct SurfaceBuffer {
|
||||||
pub buffer: AttachedBuffer,
|
pub buffer: AttachedBuffer,
|
||||||
sync_files: SmallMap<BufferResvUser, SyncFile, 1>,
|
sync_files: SmallMap<BufferResvUser, SyncFile, 1>,
|
||||||
pub release_sync: ReleaseSync,
|
pub release_sync: ReleaseSync,
|
||||||
release: Option<SurfaceBufferExplicitRelease>,
|
release: Option<SyncObjRelease>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for SurfaceBuffer {
|
impl Drop for SurfaceBuffer {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let sync_files = self.sync_files.take();
|
let sync_files = self.sync_files.take();
|
||||||
if let Some(release) = &self.release {
|
if let Some(release) = &mut self.release {
|
||||||
let Some(ctx) = self.buffer.buf.client.state.render_ctx.get() else {
|
release.signal(Some(&sync_files));
|
||||||
log::error!("Cannot signal release point because there is no render context");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let Some(ctx) = ctx.sync_obj_ctx() else {
|
|
||||||
log::error!("Cannot signal release point because there is no syncobj context");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if sync_files.is_not_empty() {
|
|
||||||
let res = ctx.import_sync_files(
|
|
||||||
&release.sync_obj,
|
|
||||||
release.point,
|
|
||||||
sync_files.iter().map(|f| &f.1),
|
|
||||||
);
|
|
||||||
match res {
|
|
||||||
Ok(_) => return,
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("Could not import sync files into sync obj: {}", ErrorFmt(e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Err(e) = ctx.signal(&release.sync_obj, release.point) {
|
|
||||||
log::error!("Could not signal release point: {}", ErrorFmt(e));
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let Some(dmabuf) = &self.buffer.buf.client_dmabuf {
|
if let Some(dmabuf) = &self.buffer.buf.client_dmabuf {
|
||||||
|
|
@ -478,7 +452,7 @@ struct PendingState {
|
||||||
layer_surface: Option<Box<PendingLayerSurfaceData>>,
|
layer_surface: Option<Box<PendingLayerSurfaceData>>,
|
||||||
subsurfaces: AHashMap<SubsurfaceId, AttachedSubsurfaceState>,
|
subsurfaces: AHashMap<SubsurfaceId, AttachedSubsurfaceState>,
|
||||||
acquire_point: Option<(Rc<SyncObj>, SyncObjPoint)>,
|
acquire_point: Option<(Rc<SyncObj>, SyncObjPoint)>,
|
||||||
release_point: Option<(Rc<SyncObj>, SyncObjPoint)>,
|
release_point: Option<SyncObjRelease>,
|
||||||
alpha_multiplier: Option<Option<f32>>,
|
alpha_multiplier: Option<Option<f32>>,
|
||||||
explicit_sync: bool,
|
explicit_sync: bool,
|
||||||
fifo_barrier_set: bool,
|
fifo_barrier_set: bool,
|
||||||
|
|
@ -499,11 +473,6 @@ impl PendingState {
|
||||||
fn merge(&mut self, next: &mut Self, client: &Rc<Client>) {
|
fn merge(&mut self, next: &mut Self, client: &Rc<Client>) {
|
||||||
// discard state
|
// discard state
|
||||||
|
|
||||||
if next.buffer.is_some() {
|
|
||||||
if let Some((sync_obj, point)) = self.release_point.take() {
|
|
||||||
client.state.signal_point(&sync_obj, point);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.presentation_feedback.clear();
|
self.presentation_feedback.clear();
|
||||||
|
|
||||||
// overwrite state
|
// overwrite state
|
||||||
|
|
@ -1123,6 +1092,9 @@ impl WlSurfaceRequestHandler for WlSurface {
|
||||||
{
|
{
|
||||||
buffer.send_release = true;
|
buffer.send_release = true;
|
||||||
}
|
}
|
||||||
|
if let Some(release) = &mut pending.release_point {
|
||||||
|
release.committed = true;
|
||||||
|
}
|
||||||
self.verify_explicit_sync(pending)?;
|
self.verify_explicit_sync(pending)?;
|
||||||
if ext.commit_requested(pending) == CommitAction::ContinueCommit {
|
if ext.commit_requested(pending) == CommitAction::ContinueCommit {
|
||||||
self.commit_timeline.commit(slf, pending)?;
|
self.commit_timeline.commit(slf, pending)?;
|
||||||
|
|
@ -1242,15 +1214,11 @@ impl WlSurface {
|
||||||
false => ReleaseSync::Implicit,
|
false => ReleaseSync::Implicit,
|
||||||
true => ReleaseSync::Explicit,
|
true => ReleaseSync::Explicit,
|
||||||
};
|
};
|
||||||
let release = pending
|
|
||||||
.release_point
|
|
||||||
.take()
|
|
||||||
.map(|(sync_obj, point)| SurfaceBufferExplicitRelease { sync_obj, point });
|
|
||||||
let surface_buffer = SurfaceBuffer {
|
let surface_buffer = SurfaceBuffer {
|
||||||
buffer,
|
buffer,
|
||||||
sync_files: Default::default(),
|
sync_files: Default::default(),
|
||||||
release_sync,
|
release_sync,
|
||||||
release,
|
release: pending.release_point.take(),
|
||||||
};
|
};
|
||||||
self.buffer.set(Some(Rc::new(surface_buffer)));
|
self.buffer.set(Some(Rc::new(surface_buffer)));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2268,3 +2236,49 @@ impl Drop for FrameRequest {
|
||||||
let _ = self.cb.client.remove_obj(&*self.cb);
|
let _ = self.cb.client.remove_obj(&*self.cb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct SyncObjRelease {
|
||||||
|
state: Rc<State>,
|
||||||
|
committed: bool,
|
||||||
|
syncobj: Option<Rc<SyncObj>>,
|
||||||
|
point: SyncObjPoint,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SyncObjRelease {
|
||||||
|
fn signal(&mut self, sync_files: Option<&SmallVec<[(BufferResvUser, SyncFile); 1]>>) {
|
||||||
|
if !self.committed {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let Some(sync_obj) = self.syncobj.take() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Some(ctx) = self.state.render_ctx.get() else {
|
||||||
|
log::error!("Cannot signal release point because there is no render context");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Some(ctx) = ctx.sync_obj_ctx() else {
|
||||||
|
log::error!("Cannot signal release point because there is no syncobj context");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if let Some(sync_files) = sync_files
|
||||||
|
&& sync_files.is_not_empty()
|
||||||
|
{
|
||||||
|
let res = ctx.import_sync_files(&sync_obj, self.point, sync_files.iter().map(|f| &f.1));
|
||||||
|
match res {
|
||||||
|
Ok(_) => return,
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Could not import sync files into sync obj: {}", ErrorFmt(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Err(e) = ctx.signal(&sync_obj, self.point) {
|
||||||
|
log::error!("Could not signal release point: {}", ErrorFmt(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for SyncObjRelease {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.signal(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
client::{Client, ClientError},
|
client::{Client, ClientError},
|
||||||
ifs::wl_surface::WlSurface,
|
ifs::wl_surface::{SyncObjRelease, WlSurface},
|
||||||
leaks::Tracker,
|
leaks::Tracker,
|
||||||
object::{Object, Version},
|
object::{Object, Version},
|
||||||
video::drm::sync_obj::SyncObjPoint,
|
video::drm::sync_obj::SyncObjPoint,
|
||||||
|
|
@ -66,7 +66,12 @@ impl WpLinuxDrmSyncobjSurfaceV1RequestHandler for WpLinuxDrmSyncobjSurfaceV1 {
|
||||||
fn set_release_point(&self, req: SetReleasePoint, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
fn set_release_point(&self, req: SetReleasePoint, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||||
let point = SyncObjPoint(req.point);
|
let point = SyncObjPoint(req.point);
|
||||||
let timeline = self.client.lookup(req.timeline)?;
|
let timeline = self.client.lookup(req.timeline)?;
|
||||||
self.surface.pending.borrow_mut().release_point = Some((timeline.sync_obj.clone(), point));
|
self.surface.pending.borrow_mut().release_point = Some(SyncObjRelease {
|
||||||
|
state: self.client.state.clone(),
|
||||||
|
committed: false,
|
||||||
|
syncobj: Some(timeline.sync_obj.clone()),
|
||||||
|
point,
|
||||||
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
20
src/state.rs
20
src/state.rs
|
|
@ -121,11 +121,7 @@ use {
|
||||||
},
|
},
|
||||||
video::{
|
video::{
|
||||||
dmabuf::DmaBufIds,
|
dmabuf::DmaBufIds,
|
||||||
drm::{
|
drm::{Drm, wait_for_sync_obj::WaitForSyncObj},
|
||||||
Drm,
|
|
||||||
sync_obj::{SyncObj, SyncObjPoint},
|
|
||||||
wait_for_sync_obj::WaitForSyncObj,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
wheel::Wheel,
|
wheel::Wheel,
|
||||||
wire::{
|
wire::{
|
||||||
|
|
@ -1360,20 +1356,6 @@ impl State {
|
||||||
seat
|
seat
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn signal_point(&self, sync_obj: &SyncObj, point: SyncObjPoint) {
|
|
||||||
let Some(ctx) = self.render_ctx.get() else {
|
|
||||||
log::error!("Cannot signal sync obj point because there is no render context");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let Some(ctx) = ctx.sync_obj_ctx() else {
|
|
||||||
log::error!("Cannot signal sync obj point because there is no syncobj context");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if let Err(e) = ctx.signal(sync_obj, point) {
|
|
||||||
log::error!("Could not signal sync obj: {}", ErrorFmt(e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_backend_idle(&self, idle: bool) {
|
pub fn set_backend_idle(&self, idle: bool) {
|
||||||
if self.idle.backend_idle.replace(idle) != idle {
|
if self.idle.backend_idle.replace(idle) != idle {
|
||||||
self.root.update_visible(self);
|
self.root.update_visible(self);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue