wl_surface: dispatch presentation feedback via presented events
This commit is contained in:
parent
01331afc6d
commit
7800488555
9 changed files with 117 additions and 47 deletions
|
|
@ -237,9 +237,6 @@ impl MetalConnector {
|
|||
}
|
||||
}
|
||||
if let Err(e) = res {
|
||||
self.render_result
|
||||
.borrow_mut()
|
||||
.discard_presentation_feedback();
|
||||
if let MetalError::Commit(DrmError::Atomic(OsError(c::EACCES))) = e {
|
||||
log::debug!("Could not perform atomic commit, likely because we're no longer the DRM master");
|
||||
return Ok(());
|
||||
|
|
|
|||
|
|
@ -1978,27 +1978,14 @@ impl MetalBackend {
|
|||
.set(tv_sec as u64 * 1_000_000_000 + tv_usec as u64 * 1000 + dd.refresh as u64);
|
||||
{
|
||||
let global = self.state.root.outputs.get(&connector.connector_id);
|
||||
let mut rr = connector.render_result.borrow_mut();
|
||||
if let Some(g) = &global {
|
||||
let refresh = dd.refresh;
|
||||
let bindings = g.global.bindings.borrow_mut();
|
||||
for fb in rr.presentation_feedbacks.drain(..) {
|
||||
if let Some(bindings) = bindings.get(&fb.client.id) {
|
||||
for binding in bindings.values() {
|
||||
fb.send_sync_output(binding);
|
||||
}
|
||||
}
|
||||
fb.send_presented(
|
||||
tv_sec as _,
|
||||
tv_usec * 1000,
|
||||
refresh,
|
||||
connector.sequence.get(),
|
||||
KIND_VSYNC | KIND_HW_COMPLETION,
|
||||
);
|
||||
let _ = fb.client.remove_obj(&*fb);
|
||||
}
|
||||
} else {
|
||||
rr.discard_presentation_feedback();
|
||||
g.presented(
|
||||
tv_sec as _,
|
||||
tv_usec * 1000,
|
||||
dd.refresh,
|
||||
connector.sequence.get(),
|
||||
KIND_VSYNC | KIND_HW_COMPLETION,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -505,6 +505,7 @@ fn create_dummy_output(state: &Rc<State>) {
|
|||
title_visible: Cell::new(false),
|
||||
schedule,
|
||||
latch_event: Default::default(),
|
||||
presentation_event: Default::default(),
|
||||
});
|
||||
let dummy_workspace = Rc::new(WorkspaceNode {
|
||||
id: state.node_ids.next(),
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ impl WlCompositorRequestHandler for WlCompositor {
|
|||
type Error = WlCompositorError;
|
||||
|
||||
fn create_surface(&self, req: CreateSurface, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let surface = Rc::new(WlSurface::new(req.id, &self.client, self.version));
|
||||
let surface = Rc::new_cyclic(|slf| WlSurface::new(req.id, &self.client, self.version, slf));
|
||||
track!(self.client, surface);
|
||||
self.client.add_client_obj(&surface)?;
|
||||
if self.client.is_xwayland {
|
||||
|
|
|
|||
|
|
@ -63,13 +63,15 @@ use {
|
|||
rect::{DamageQueue, Rect, Region},
|
||||
renderer::Renderer,
|
||||
tree::{
|
||||
ContainerNode, FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, NodeVisitorBase,
|
||||
OutputNode, OutputNodeId, PlaceholderNode, ToplevelNode,
|
||||
ContainerNode, FindTreeResult, FoundNode, LatchListener, Node, NodeId, NodeVisitor,
|
||||
NodeVisitorBase, OutputNode, OutputNodeId, PlaceholderNode, PresentationListener,
|
||||
ToplevelNode,
|
||||
},
|
||||
utils::{
|
||||
cell_ext::CellExt, clonecell::CloneCell, copyhashmap::CopyHashMap,
|
||||
double_buffered::DoubleBuffered, errorfmt::ErrorFmt, linkedlist::LinkedList,
|
||||
numcell::NumCell, smallmap::SmallMap, transform_ext::TransformExt,
|
||||
double_buffered::DoubleBuffered, errorfmt::ErrorFmt, event_listener::EventListener,
|
||||
linkedlist::LinkedList, numcell::NumCell, smallmap::SmallMap,
|
||||
transform_ext::TransformExt,
|
||||
},
|
||||
video::{
|
||||
dmabuf::DMA_BUF_SYNC_READ,
|
||||
|
|
@ -91,7 +93,7 @@ use {
|
|||
fmt::{Debug, Formatter},
|
||||
mem,
|
||||
ops::{Deref, DerefMut},
|
||||
rc::Rc,
|
||||
rc::{Rc, Weak},
|
||||
},
|
||||
thiserror::Error,
|
||||
zwp_idle_inhibitor_v1::ZwpIdleInhibitorV1,
|
||||
|
|
@ -282,7 +284,8 @@ pub struct WlSurface {
|
|||
pub children: RefCell<Option<Box<ParentData>>>,
|
||||
ext: CloneCell<Rc<dyn SurfaceExt>>,
|
||||
pub frame_requests: RefCell<Vec<Rc<WlCallback>>>,
|
||||
pub presentation_feedback: RefCell<Vec<Rc<WpPresentationFeedback>>>,
|
||||
presentation_feedback: RefCell<Vec<Rc<WpPresentationFeedback>>>,
|
||||
latched_presentation_feedback: RefCell<Vec<Rc<WpPresentationFeedback>>>,
|
||||
seat_state: NodeSeatState,
|
||||
toplevel: CloneCell<Option<Rc<dyn ToplevelNode>>>,
|
||||
cursors: SmallMap<CursorUserId, Rc<CursorSurface>, 1>,
|
||||
|
|
@ -306,6 +309,10 @@ pub struct WlSurface {
|
|||
alpha_modifier: CloneCell<Option<Rc<WpAlphaModifierSurfaceV1>>>,
|
||||
alpha: Cell<Option<f32>>,
|
||||
pub text_input_connections: SmallMap<SeatId, Rc<TextInputConnection>, 1>,
|
||||
latch_listener: EventListener<dyn LatchListener>,
|
||||
presentation_listener: EventListener<dyn PresentationListener>,
|
||||
commit_version: NumCell<u64>,
|
||||
latched_commit_version: Cell<u64>,
|
||||
}
|
||||
|
||||
impl Debug for WlSurface {
|
||||
|
|
@ -566,7 +573,7 @@ pub struct StackElement {
|
|||
}
|
||||
|
||||
impl WlSurface {
|
||||
pub fn new(id: WlSurfaceId, client: &Rc<Client>, version: Version) -> Self {
|
||||
pub fn new(id: WlSurfaceId, client: &Rc<Client>, version: Version, slf: &Weak<Self>) -> Self {
|
||||
Self {
|
||||
id,
|
||||
node_id: client.state.node_ids.next(),
|
||||
|
|
@ -599,6 +606,7 @@ impl WlSurface {
|
|||
ext: CloneCell::new(client.state.none_surface_ext.clone()),
|
||||
frame_requests: Default::default(),
|
||||
presentation_feedback: Default::default(),
|
||||
latched_presentation_feedback: Default::default(),
|
||||
seat_state: Default::default(),
|
||||
toplevel: Default::default(),
|
||||
cursors: Default::default(),
|
||||
|
|
@ -622,6 +630,10 @@ impl WlSurface {
|
|||
alpha_modifier: Default::default(),
|
||||
alpha: Default::default(),
|
||||
text_input_connections: Default::default(),
|
||||
latch_listener: EventListener::new(slf.clone()),
|
||||
presentation_listener: EventListener::new(slf.clone()),
|
||||
commit_version: Default::default(),
|
||||
latched_commit_version: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -652,6 +664,9 @@ impl WlSurface {
|
|||
if old.id == output.id {
|
||||
return;
|
||||
}
|
||||
if self.visible.get() {
|
||||
self.attach_events_to_output(output);
|
||||
}
|
||||
output.global.send_enter(self);
|
||||
old.global.send_leave(self);
|
||||
if old.global.persistent.scale.get() != output.global.persistent.scale.get() {
|
||||
|
|
@ -1230,14 +1245,15 @@ impl WlSurface {
|
|||
};
|
||||
self.buffer_had_frame_request
|
||||
.set(had_frame_requests || has_frame_requests);
|
||||
{
|
||||
let has_presentation_feedback = {
|
||||
let mut fbs = self.presentation_feedback.borrow_mut();
|
||||
for fb in fbs.drain(..) {
|
||||
fb.send_discarded();
|
||||
let _ = self.client.remove_obj(&*fb);
|
||||
}
|
||||
mem::swap(fbs.deref_mut(), &mut pending.presentation_feedback);
|
||||
}
|
||||
fbs.is_not_empty()
|
||||
};
|
||||
{
|
||||
if let Some(region) = pending.input_region.take() {
|
||||
self.input_region.set(region);
|
||||
|
|
@ -1278,6 +1294,10 @@ impl WlSurface {
|
|||
}
|
||||
self.ext.get().after_apply_commit();
|
||||
if self.visible.get() {
|
||||
let output = self.output.get();
|
||||
if has_presentation_feedback {
|
||||
self.latch_listener.attach(&output.latch_event);
|
||||
}
|
||||
if damage_full {
|
||||
let mut damage = buffer_abs_pos
|
||||
.with_size(max_surface_size.0, max_surface_size.1)
|
||||
|
|
@ -1327,6 +1347,7 @@ impl WlSurface {
|
|||
}
|
||||
}
|
||||
}
|
||||
self.commit_version.fetch_add(1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -1469,10 +1490,17 @@ impl WlSurface {
|
|||
}
|
||||
}
|
||||
|
||||
fn attach_events_to_output(&self, output: &OutputNode) {
|
||||
self.latch_listener.attach(&output.latch_event);
|
||||
}
|
||||
|
||||
pub fn set_visible(&self, visible: bool) {
|
||||
if self.visible.replace(visible) == visible {
|
||||
return;
|
||||
}
|
||||
if visible {
|
||||
self.attach_events_to_output(&self.output.get());
|
||||
}
|
||||
for (_, inhibitor) in &self.idle_inhibitors {
|
||||
if visible {
|
||||
inhibitor.activate();
|
||||
|
|
@ -1586,6 +1614,7 @@ impl Object for WlSurface {
|
|||
self.idle_inhibitors.clear();
|
||||
mem::take(self.pending.borrow_mut().deref_mut());
|
||||
self.presentation_feedback.borrow_mut().clear();
|
||||
self.latched_presentation_feedback.borrow_mut().clear();
|
||||
self.viewporter.take();
|
||||
self.fractional_scale.take();
|
||||
self.tearing_control.take();
|
||||
|
|
@ -2053,3 +2082,49 @@ impl DamageMatrix {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LatchListener for WlSurface {
|
||||
fn after_latch(self: Rc<Self>) {
|
||||
if self.visible.get() {
|
||||
if self.latched_commit_version.get() < self.commit_version.get() {
|
||||
let latched = &mut *self.latched_presentation_feedback.borrow_mut();
|
||||
for pf in latched.drain(..) {
|
||||
pf.send_discarded();
|
||||
let _ = pf.client.remove_obj(&*pf);
|
||||
}
|
||||
latched.append(&mut self.presentation_feedback.borrow_mut());
|
||||
if latched.is_not_empty() {
|
||||
self.presentation_listener
|
||||
.attach(&self.output.get().presentation_event);
|
||||
}
|
||||
self.latched_commit_version.set(self.commit_version.get());
|
||||
}
|
||||
}
|
||||
self.latch_listener.detach();
|
||||
}
|
||||
}
|
||||
|
||||
impl PresentationListener for WlSurface {
|
||||
fn presented(
|
||||
self: Rc<Self>,
|
||||
output: &OutputNode,
|
||||
tv_sec: u64,
|
||||
tv_nsec: u32,
|
||||
refresh: u32,
|
||||
seq: u64,
|
||||
flags: u32,
|
||||
) {
|
||||
let bindings = output.global.bindings.borrow();
|
||||
let bindings = bindings.get(&self.client.id);
|
||||
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);
|
||||
}
|
||||
}
|
||||
pf.send_presented(tv_sec, tv_nsec, refresh, seq, flags);
|
||||
let _ = pf.client.remove_obj(&*pf);
|
||||
}
|
||||
self.presentation_listener.detach();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,6 +107,10 @@ impl Cursor for CursorSurface {
|
|||
fr.send_discarded();
|
||||
let _ = fr.client.remove_obj(fr.deref());
|
||||
}
|
||||
for fr in node.latched_presentation_feedback.borrow_mut().drain(..) {
|
||||
fr.send_discarded();
|
||||
let _ = fr.client.remove_obj(fr.deref());
|
||||
}
|
||||
node.node_visit_children(self);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ use {
|
|||
zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
|
||||
SurfaceBuffer, WlSurface,
|
||||
},
|
||||
wp_presentation_feedback::WpPresentationFeedback,
|
||||
},
|
||||
rect::Rect,
|
||||
renderer::renderer_base::RendererBase,
|
||||
|
|
@ -33,7 +32,6 @@ pub mod renderer_base;
|
|||
|
||||
pub struct RenderResult {
|
||||
pub frame_requests: Vec<Rc<WlCallback>>,
|
||||
pub presentation_feedbacks: Vec<Rc<WpPresentationFeedback>>,
|
||||
pub output_id: OutputNodeId,
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +39,6 @@ impl Default for RenderResult {
|
|||
fn default() -> Self {
|
||||
Self {
|
||||
frame_requests: Default::default(),
|
||||
presentation_feedbacks: Default::default(),
|
||||
output_id: OutputNodeId::none(),
|
||||
}
|
||||
}
|
||||
|
|
@ -54,13 +51,6 @@ impl RenderResult {
|
|||
let _ = fr.client.remove_obj(&*fr);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn discard_presentation_feedback(&mut self) {
|
||||
for fb in self.presentation_feedbacks.drain(..) {
|
||||
fb.send_discarded();
|
||||
let _ = fb.client.remove_obj(&*fb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for RenderResult {
|
||||
|
|
@ -442,10 +432,6 @@ impl Renderer<'_> {
|
|||
let mut fr = surface.frame_requests.borrow_mut();
|
||||
result.frame_requests.extend(fr.drain(..));
|
||||
}
|
||||
{
|
||||
let mut fbs = surface.presentation_feedback.borrow_mut();
|
||||
result.presentation_feedbacks.extend(fbs.drain(..));
|
||||
}
|
||||
surface.presented(result.output_id);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@ impl ConnectorHandler {
|
|||
title_visible: Default::default(),
|
||||
schedule,
|
||||
latch_event: Default::default(),
|
||||
presentation_event: Default::default(),
|
||||
});
|
||||
on.update_visible();
|
||||
on.update_rects();
|
||||
|
|
|
|||
|
|
@ -81,12 +81,25 @@ pub struct OutputNode {
|
|||
pub title_visible: Cell<bool>,
|
||||
pub schedule: Rc<OutputSchedule>,
|
||||
pub latch_event: EventSource<dyn LatchListener>,
|
||||
pub presentation_event: EventSource<dyn PresentationListener>,
|
||||
}
|
||||
|
||||
pub trait LatchListener {
|
||||
fn after_latch(self: Rc<Self>);
|
||||
}
|
||||
|
||||
pub trait PresentationListener {
|
||||
fn presented(
|
||||
self: Rc<Self>,
|
||||
output: &OutputNode,
|
||||
tv_sec: u64,
|
||||
tv_nsec: u32,
|
||||
refresh: u32,
|
||||
seq: u64,
|
||||
flags: u32,
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum PointerType {
|
||||
Seat(SeatId),
|
||||
|
|
@ -113,6 +126,12 @@ impl OutputNode {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn presented(&self, tv_sec: u64, tv_nsec: u32, refresh: u32, seq: u64, flags: u32) {
|
||||
for listener in self.presentation_event.iter() {
|
||||
listener.presented(self, tv_sec, tv_nsec, refresh, seq, flags);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_exclusive_zones(self: &Rc<Self>) {
|
||||
let mut exclusive = ExclusiveSize::default();
|
||||
for layer in &self.layers {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue