wayland_server: make frame callbacks, release buffers. logging

This commit is contained in:
galister
2025-12-26 02:02:19 +09:00
parent b1fba81e08
commit db74874a80
4 changed files with 91 additions and 101 deletions

View File

@@ -4,7 +4,7 @@ use smithay::input::{Seat, SeatHandler, SeatState};
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel; use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
use smithay::reexports::wayland_server; use smithay::reexports::wayland_server;
use smithay::reexports::wayland_server::Resource; use smithay::reexports::wayland_server::Resource;
use smithay::reexports::wayland_server::protocol::{wl_buffer, wl_output, wl_seat, wl_surface}; use smithay::reexports::wayland_server::protocol::{wl_buffer, wl_output, wl_seat};
use smithay::wayland::buffer::BufferHandler; use smithay::wayland::buffer::BufferHandler;
use smithay::wayland::dmabuf::{ use smithay::wayland::dmabuf::{
DmabufFeedback, DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier, get_dmabuf, DmabufFeedback, DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier, get_dmabuf,
@@ -21,9 +21,7 @@ use std::os::fd::OwnedFd;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use smithay::utils::Serial; use smithay::utils::Serial;
use smithay::wayland::compositor::{ use smithay::wayland::compositor::{self, BufferAssignment, SurfaceAttributes};
self, BufferAssignment, SurfaceAttributes, TraversalAction, with_surface_tree_downward,
};
use smithay::wayland::selection::SelectionHandler; use smithay::wayland::selection::SelectionHandler;
use smithay::wayland::selection::data_device::{ use smithay::wayland::selection::data_device::{
@@ -36,8 +34,8 @@ use wayland_server::Client;
use wayland_server::backend::{ClientData, ClientId, DisconnectReason}; use wayland_server::backend::{ClientData, ClientId, DisconnectReason};
use wayland_server::protocol::wl_surface::WlSurface; use wayland_server::protocol::wl_surface::WlSurface;
use crate::backend::wayvr::SurfaceBufWithImage;
use crate::backend::wayvr::image_importer::ImageImporter; use crate::backend::wayvr::image_importer::ImageImporter;
use crate::backend::wayvr::{SurfaceBufWithImage, time};
use crate::ipc::event_queue::SyncEventQueue; use crate::ipc::event_queue::SyncEventQueue;
use super::WayVRTask; use super::WayVRTask;
@@ -83,38 +81,43 @@ impl compositor::CompositorHandler for Application {
match attrs.buffer.take() { match attrs.buffer.take() {
Some(BufferAssignment::NewBuffer(buffer)) => { Some(BufferAssignment::NewBuffer(buffer)) => {
let current = SurfaceBufWithImage::get_from_surface(states);
if current.is_none_or(|c| c.buffer != buffer) {
match buffer_type(&buffer) { match buffer_type(&buffer) {
Some(BufferType::Dma) => { Some(BufferType::Dma) => {
let dmabuf = get_dmabuf(&buffer).unwrap(); // always Ok due to buffer_type let dmabuf = get_dmabuf(&buffer).unwrap(); // always Ok due to buffer_type
if let Ok(image) = if let Ok(image) = self
self.image_importer.get_or_import_dmabuf(dmabuf.clone()) .image_importer
.get_or_import_dmabuf(dmabuf.clone())
.inspect_err(|e| {
log::warn!("wayland_server failed to import DMA-buf: {e:?}")
})
{ {
let sbwi = SurfaceBufWithImage { let sbwi = SurfaceBufWithImage {
image, image,
buffer,
transform: wl_transform_to_frame_transform( transform: wl_transform_to_frame_transform(
attrs.buffer_transform, attrs.buffer_transform,
), ),
scale: attrs.buffer_scale, scale: attrs.buffer_scale,
dmabuf: true,
}; };
sbwi.apply_to_surface(states); sbwi.apply_to_surface(states);
} }
} }
Some(BufferType::Shm) => { Some(BufferType::Shm) => {
let _ = with_buffer_contents(&buffer, |data, size, buf| { let _ = with_buffer_contents(&buffer, |data, size, buf| {
if let Ok(image) = if let Ok(image) = self
self.image_importer.import_shm(data, size, buf) .image_importer
.import_shm(data, size, buf)
.inspect_err(|e| {
log::warn!("wayland_server failed to import SHM: {e:?}")
})
{ {
let sbwi = SurfaceBufWithImage { let sbwi = SurfaceBufWithImage {
image, image,
buffer: buffer.clone(),
transform: wl_transform_to_frame_transform( transform: wl_transform_to_frame_transform(
attrs.buffer_transform, attrs.buffer_transform,
), ),
scale: attrs.buffer_scale, scale: attrs.buffer_scale,
dmabuf: false,
}; };
sbwi.apply_to_surface(states); sbwi.apply_to_surface(states);
} }
@@ -122,15 +125,19 @@ impl compositor::CompositorHandler for Application {
} }
Some(BufferType::SinglePixel) => { Some(BufferType::SinglePixel) => {
let spb = get_single_pixel_buffer(&buffer).unwrap(); // always Ok let spb = get_single_pixel_buffer(&buffer).unwrap(); // always Ok
if let Ok(image) = self.image_importer.import_spb(spb) { if let Ok(image) =
self.image_importer.import_spb(spb).inspect_err(|e| {
log::warn!("wayland_server failed to import SPB: {e:?}")
})
{
let sbwi = SurfaceBufWithImage { let sbwi = SurfaceBufWithImage {
image, image,
buffer,
transform: wl_transform_to_frame_transform( transform: wl_transform_to_frame_transform(
// does this even matter // does this even matter
attrs.buffer_transform, attrs.buffer_transform,
), ),
scale: attrs.buffer_scale, scale: attrs.buffer_scale,
dmabuf: false,
}; };
sbwi.apply_to_surface(states); sbwi.apply_to_surface(states);
} }
@@ -138,11 +145,17 @@ impl compositor::CompositorHandler for Application {
Some(other) => log::warn!("Unsupported wl_buffer format: {other:?}"), Some(other) => log::warn!("Unsupported wl_buffer format: {other:?}"),
None => { /* don't draw anything */ } None => { /* don't draw anything */ }
} }
} buffer.release();
} }
Some(BufferAssignment::Removed) => {} Some(BufferAssignment::Removed) => {}
None => {} None => {}
} }
let t = time::get_millis() as u32;
let callbacks = std::mem::take(&mut attrs.frame_callbacks);
for cb in callbacks {
cb.done(t);
}
}); });
self.redraw_requests.insert(surface.id()); self.redraw_requests.insert(surface.id());
@@ -286,28 +299,6 @@ delegate_seat!(Application);
delegate_data_device!(Application); delegate_data_device!(Application);
delegate_output!(Application); delegate_output!(Application);
pub fn send_frames_surface_tree(surface: &wl_surface::WlSurface, time: u32) {
with_surface_tree_downward(
surface,
(),
|_, _, &()| TraversalAction::DoChildren(()),
|_surf, states, &()| {
// the surface may not have any user_data if it is a subsurface and has not
// yet been committed
for callback in states
.cached_state
.get::<SurfaceAttributes>()
.current()
.frame_callbacks
.drain(..)
{
callback.done(time);
}
},
|_, _, &()| true,
);
}
fn wl_transform_to_frame_transform( fn wl_transform_to_frame_transform(
transform: wl_output::Transform, transform: wl_output::Transform,
) -> wlx_capture::frame::Transform { ) -> wlx_capture::frame::Transform {

View File

@@ -14,7 +14,7 @@ use smallvec::SmallVec;
use smithay::{ use smithay::{
input::{SeatState, keyboard::XkbConfig}, input::{SeatState, keyboard::XkbConfig},
output::{Mode, Output}, output::{Mode, Output},
reexports::wayland_server::{self, backend::ClientId, protocol::wl_buffer}, reexports::wayland_server::{self, backend::ClientId},
wayland::{ wayland::{
compositor::{self, SurfaceData, with_states}, compositor::{self, SurfaceData, with_states},
dmabuf::{DmabufFeedbackBuilder, DmabufState}, dmabuf::{DmabufFeedbackBuilder, DmabufState},
@@ -26,8 +26,6 @@ use smithay::{
use std::{ use std::{
cell::RefCell, cell::RefCell,
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
mem::MaybeUninit,
rc::Rc,
sync::Arc, sync::Arc,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
@@ -112,7 +110,7 @@ pub struct Config {
pub struct WayVRState { pub struct WayVRState {
time_start: u64, time_start: u64,
pub manager: client::WayVRCompositor, pub manager: client::WayVRCompositor,
pub wm: Rc<RefCell<window::WindowManager>>, pub wm: window::WindowManager,
pub processes: process::ProcessVec, pub processes: process::ProcessVec,
pub config: Config, pub config: Config,
pub tasks: SyncEventQueue<WayVRTask>, pub tasks: SyncEventQueue<WayVRTask>,
@@ -241,7 +239,7 @@ impl WayVR {
time_start, time_start,
manager: client::WayVRCompositor::new(state, display, seat_keyboard, seat_pointer)?, manager: client::WayVRCompositor::new(state, display, seat_keyboard, seat_pointer)?,
processes: ProcessVec::new(), processes: ProcessVec::new(),
wm: Rc::new(RefCell::new(window::WindowManager::new())), wm: window::WindowManager::new(),
config, config,
ticks: 0, ticks: 0,
tasks, tasks,
@@ -307,11 +305,7 @@ impl WayVR {
continue; continue;
}; };
let window_handle = self let window_handle = self.state.wm.create_window(&toplevel, process_handle);
.state
.wm
.borrow_mut()
.create_window(&toplevel, process_handle);
let title: Arc<str> = with_states(toplevel.wl_surface(), |states| { let title: Arc<str> = with_states(toplevel.wl_surface(), |states| {
states states
@@ -353,8 +347,8 @@ impl WayVR {
continue; continue;
} }
let mut wm = self.state.wm.borrow_mut(); let Some(window_handle) = self.state.wm.find_window_handle(&toplevel)
let Some(window_handle) = wm.find_window_handle(&toplevel) else { else {
log::warn!("DropToplevel: Couldn't find matching window handle"); log::warn!("DropToplevel: Couldn't find matching window handle");
continue; continue;
}; };
@@ -365,9 +359,7 @@ impl WayVR {
))); )));
} }
wm.remove_window(window_handle); self.state.wm.remove_window(window_handle);
drop(wm);
} }
} }
WayVRTask::ProcessTerminationRequest(process_handle) => { WayVRTask::ProcessTerminationRequest(process_handle) => {
@@ -404,7 +396,7 @@ impl WayVRState {
if self.mouse_freeze > Instant::now() { if self.mouse_freeze > Instant::now() {
return; return;
} }
if let Some(window) = self.wm.borrow_mut().windows.get_mut(&handle) { if let Some(window) = self.wm.windows.get_mut(&handle) {
window.send_mouse_move(&mut self.manager, x, y); window.send_mouse_move(&mut self.manager, x, y);
} }
} }
@@ -413,7 +405,7 @@ impl WayVRState {
self.mouse_freeze = self.mouse_freeze =
Instant::now() + Duration::from_millis(self.config.click_freeze_time_ms as _); Instant::now() + Duration::from_millis(self.config.click_freeze_time_ms as _);
if let Some(window) = self.wm.borrow_mut().windows.get_mut(&handle) { if let Some(window) = self.wm.windows.get_mut(&handle) {
window.send_mouse_down(&mut self.manager, index); window.send_mouse_down(&mut self.manager, index);
} }
} }
@@ -563,10 +555,10 @@ struct SurfaceBufWithImageContainer {
#[derive(Clone)] #[derive(Clone)]
pub struct SurfaceBufWithImage { pub struct SurfaceBufWithImage {
buffer: wl_buffer::WlBuffer,
pub image: Arc<ImageView>, pub image: Arc<ImageView>,
pub transform: Transform, pub transform: Transform,
pub scale: i32, pub scale: i32,
pub dmabuf: bool,
} }
impl SurfaceBufWithImage { impl SurfaceBufWithImage {
@@ -575,7 +567,11 @@ impl SurfaceBufWithImage {
if let Some(container) = surface_data.data_map.get::<SurfaceBufWithImageContainer>() { if let Some(container) = surface_data.data_map.get::<SurfaceBufWithImageContainer>() {
container.inner.replace(self); container.inner.replace(self);
} else { } else {
surface_data.data_map.insert_if_missing(|| self); surface_data
.data_map
.insert_if_missing(|| SurfaceBufWithImageContainer {
inner: RefCell::new(self),
});
} }
} }

View File

@@ -199,7 +199,6 @@ impl Connection {
list: params list: params
.wayland_state .wayland_state
.wm .wm
.borrow_mut()
.windows .windows
.iter() .iter()
.map(|(handle, win)| packet_server::WvrWindow { .map(|(handle, win)| packet_server::WvrWindow {
@@ -222,7 +221,6 @@ impl Connection {
if let Some(window) = params if let Some(window) = params
.wayland_state .wayland_state
.wm .wm
.borrow_mut()
.windows .windows
.get_mut(&wayvr::window::WindowHandle::from_packet(handle)) .get_mut(&wayvr::window::WindowHandle::from_packet(handle))
{ {

View File

@@ -12,7 +12,7 @@ use crate::{
backend::{ backend::{
XrBackend, XrBackend,
input::{self, HoverResult}, input::{self, HoverResult},
wayvr::{self, SurfaceBufWithImage, WayVR, window::WindowManager}, wayvr::{self, SurfaceBufWithImage, WayVR},
}, },
graphics::{ExtentExt, WGfxExtras}, graphics::{ExtentExt, WGfxExtras},
ipc::{event_queue::SyncEventQueue, signal::WayVRSignal}, ipc::{event_queue::SyncEventQueue, signal::WayVRSignal},
@@ -84,7 +84,6 @@ pub struct WayVRBackend {
interaction_transform: Option<Affine2>, interaction_transform: Option<Affine2>,
window: wayvr::window::WindowHandle, window: wayvr::window::WindowHandle,
wayvr: Rc<RefCell<WayVRData>>, wayvr: Rc<RefCell<WayVRData>>,
wm: Rc<RefCell<WindowManager>>,
just_resumed: bool, just_resumed: bool,
meta: Option<FrameMeta>, meta: Option<FrameMeta>,
stereo: Option<StereoMode>, stereo: Option<StereoMode>,
@@ -98,12 +97,10 @@ impl WayVRBackend {
wayvr: Rc<RefCell<WayVRData>>, wayvr: Rc<RefCell<WayVRData>>,
window: wayvr::window::WindowHandle, window: wayvr::window::WindowHandle,
) -> anyhow::Result<Self> { ) -> anyhow::Result<Self> {
let wm = wayvr.borrow().data.state.wm.clone();
Ok(Self { Ok(Self {
name, name,
pipeline: None, pipeline: None,
wayvr, wayvr,
wm,
window, window,
mouse_transform: Affine2::IDENTITY, mouse_transform: Affine2::IDENTITY,
interaction_transform: None, interaction_transform: None,
@@ -134,8 +131,8 @@ impl OverlayBackend for WayVRBackend {
} }
fn should_render(&mut self, app: &mut AppState) -> anyhow::Result<ShouldRender> { fn should_render(&mut self, app: &mut AppState) -> anyhow::Result<ShouldRender> {
let wm = self.wm.borrow(); let wayvr = &self.wayvr.borrow().data;
let Some(window) = wm.windows.get(&self.window) else { let Some(window) = wayvr.state.wm.windows.get(&self.window) else {
log::debug!( log::debug!(
"{:?}: WayVR overlay without matching window entry", "{:?}: WayVR overlay without matching window entry",
self.name self.name
@@ -175,12 +172,19 @@ impl OverlayBackend for WayVRBackend {
.as_ref() .as_ref()
.is_none_or(|i| *i.image() != *surf.image.image()) .is_none_or(|i| *i.image() != *surf.image.image())
{ {
log::trace!(
"{}: new {} image",
self.name,
surf.dmabuf.then_some("DMA-buf").unwrap_or("SHM")
);
self.cur_image = Some(surf.image); self.cur_image = Some(surf.image);
Ok(ShouldRender::Should) Ok(ShouldRender::Should)
} else { } else {
log::trace!("{}: no new image", self.name);
Ok(ShouldRender::Can) Ok(ShouldRender::Can)
} }
} else { } else {
log::trace!("{}: no buffer for wl_surface", self.name);
Ok(ShouldRender::Unable) Ok(ShouldRender::Unable)
} }
}) })
@@ -215,12 +219,13 @@ impl OverlayBackend for WayVRBackend {
} }
fn on_hover(&mut self, _app: &mut state::AppState, hit: &input::PointerHit) -> HoverResult { fn on_hover(&mut self, _app: &mut state::AppState, hit: &input::PointerHit) -> HoverResult {
if let Some(window) = self.wm.borrow().windows.get(&self.window) { let wayvr = &mut self.wayvr.borrow_mut().data;
if let Some((x, y)) = wayvr.state.wm.windows.get(&self.window).map(|window| {
let pos = self.mouse_transform.transform_point2(hit.uv); let pos = self.mouse_transform.transform_point2(hit.uv);
let x = ((pos.x * (window.size_x as f32)) as u32).max(0); let x = ((pos.x * (window.size_x as f32)) as u32).max(0);
let y = ((pos.y * (window.size_y as f32)) as u32).max(0); let y = ((pos.y * (window.size_y as f32)) as u32).max(0);
(x, y)
let wayvr = &mut self.wayvr.borrow_mut().data; }) {
wayvr.state.send_mouse_move(self.window, x, y); wayvr.state.send_mouse_move(self.window, x, y);
} }