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_server;
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::dmabuf::{
DmabufFeedback, DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier, get_dmabuf,
@@ -21,9 +21,7 @@ use std::os::fd::OwnedFd;
use std::sync::{Arc, Mutex};
use smithay::utils::Serial;
use smithay::wayland::compositor::{
self, BufferAssignment, SurfaceAttributes, TraversalAction, with_surface_tree_downward,
};
use smithay::wayland::compositor::{self, BufferAssignment, SurfaceAttributes};
use smithay::wayland::selection::SelectionHandler;
use smithay::wayland::selection::data_device::{
@@ -36,8 +34,8 @@ use wayland_server::Client;
use wayland_server::backend::{ClientData, ClientId, DisconnectReason};
use wayland_server::protocol::wl_surface::WlSurface;
use crate::backend::wayvr::SurfaceBufWithImage;
use crate::backend::wayvr::image_importer::ImageImporter;
use crate::backend::wayvr::{SurfaceBufWithImage, time};
use crate::ipc::event_queue::SyncEventQueue;
use super::WayVRTask;
@@ -83,66 +81,81 @@ impl compositor::CompositorHandler for Application {
match attrs.buffer.take() {
Some(BufferAssignment::NewBuffer(buffer)) => {
let current = SurfaceBufWithImage::get_from_surface(states);
if current.is_none_or(|c| c.buffer != buffer) {
match buffer_type(&buffer) {
Some(BufferType::Dma) => {
let dmabuf = get_dmabuf(&buffer).unwrap(); // always Ok due to buffer_type
if let Ok(image) =
self.image_importer.get_or_import_dmabuf(dmabuf.clone())
match buffer_type(&buffer) {
Some(BufferType::Dma) => {
let dmabuf = get_dmabuf(&buffer).unwrap(); // always Ok due to buffer_type
if let Ok(image) = self
.image_importer
.get_or_import_dmabuf(dmabuf.clone())
.inspect_err(|e| {
log::warn!("wayland_server failed to import DMA-buf: {e:?}")
})
{
let sbwi = SurfaceBufWithImage {
image,
transform: wl_transform_to_frame_transform(
attrs.buffer_transform,
),
scale: attrs.buffer_scale,
dmabuf: true,
};
sbwi.apply_to_surface(states);
}
}
Some(BufferType::Shm) => {
let _ = with_buffer_contents(&buffer, |data, size, buf| {
if let Ok(image) = self
.image_importer
.import_shm(data, size, buf)
.inspect_err(|e| {
log::warn!("wayland_server failed to import SHM: {e:?}")
})
{
let sbwi = SurfaceBufWithImage {
image,
buffer,
transform: wl_transform_to_frame_transform(
attrs.buffer_transform,
),
scale: attrs.buffer_scale,
dmabuf: false,
};
sbwi.apply_to_surface(states);
}
}
Some(BufferType::Shm) => {
let _ = with_buffer_contents(&buffer, |data, size, buf| {
if let Ok(image) =
self.image_importer.import_shm(data, size, buf)
{
let sbwi = SurfaceBufWithImage {
image,
buffer: buffer.clone(),
transform: wl_transform_to_frame_transform(
attrs.buffer_transform,
),
scale: attrs.buffer_scale,
};
sbwi.apply_to_surface(states);
}
});
}
Some(BufferType::SinglePixel) => {
let spb = get_single_pixel_buffer(&buffer).unwrap(); // always Ok
if let Ok(image) = self.image_importer.import_spb(spb) {
let sbwi = SurfaceBufWithImage {
image,
buffer,
transform: wl_transform_to_frame_transform(
// does this even matter
attrs.buffer_transform,
),
scale: attrs.buffer_scale,
};
sbwi.apply_to_surface(states);
}
}
Some(other) => log::warn!("Unsupported wl_buffer format: {other:?}"),
None => { /* don't draw anything */ }
});
}
Some(BufferType::SinglePixel) => {
let spb = get_single_pixel_buffer(&buffer).unwrap(); // always Ok
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 {
image,
transform: wl_transform_to_frame_transform(
// does this even matter
attrs.buffer_transform,
),
scale: attrs.buffer_scale,
dmabuf: false,
};
sbwi.apply_to_surface(states);
}
}
Some(other) => log::warn!("Unsupported wl_buffer format: {other:?}"),
None => { /* don't draw anything */ }
}
buffer.release();
}
Some(BufferAssignment::Removed) => {}
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());
@@ -286,28 +299,6 @@ delegate_seat!(Application);
delegate_data_device!(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(
transform: wl_output::Transform,
) -> wlx_capture::frame::Transform {

View File

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

View File

@@ -12,7 +12,7 @@ use crate::{
backend::{
XrBackend,
input::{self, HoverResult},
wayvr::{self, SurfaceBufWithImage, WayVR, window::WindowManager},
wayvr::{self, SurfaceBufWithImage, WayVR},
},
graphics::{ExtentExt, WGfxExtras},
ipc::{event_queue::SyncEventQueue, signal::WayVRSignal},
@@ -84,7 +84,6 @@ pub struct WayVRBackend {
interaction_transform: Option<Affine2>,
window: wayvr::window::WindowHandle,
wayvr: Rc<RefCell<WayVRData>>,
wm: Rc<RefCell<WindowManager>>,
just_resumed: bool,
meta: Option<FrameMeta>,
stereo: Option<StereoMode>,
@@ -98,12 +97,10 @@ impl WayVRBackend {
wayvr: Rc<RefCell<WayVRData>>,
window: wayvr::window::WindowHandle,
) -> anyhow::Result<Self> {
let wm = wayvr.borrow().data.state.wm.clone();
Ok(Self {
name,
pipeline: None,
wayvr,
wm,
window,
mouse_transform: Affine2::IDENTITY,
interaction_transform: None,
@@ -134,8 +131,8 @@ impl OverlayBackend for WayVRBackend {
}
fn should_render(&mut self, app: &mut AppState) -> anyhow::Result<ShouldRender> {
let wm = self.wm.borrow();
let Some(window) = wm.windows.get(&self.window) else {
let wayvr = &self.wayvr.borrow().data;
let Some(window) = wayvr.state.wm.windows.get(&self.window) else {
log::debug!(
"{:?}: WayVR overlay without matching window entry",
self.name
@@ -175,12 +172,19 @@ impl OverlayBackend for WayVRBackend {
.as_ref()
.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);
Ok(ShouldRender::Should)
} else {
log::trace!("{}: no new image", self.name);
Ok(ShouldRender::Can)
}
} else {
log::trace!("{}: no buffer for wl_surface", self.name);
Ok(ShouldRender::Unable)
}
})
@@ -215,12 +219,13 @@ impl OverlayBackend for WayVRBackend {
}
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 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 wayvr = &mut self.wayvr.borrow_mut().data;
(x, y)
}) {
wayvr.state.send_mouse_move(self.window, x, y);
}