Skip to content

Commit

Permalink
WayVR: Add dmabuf (backend_drm) to the compositor. Fixes crash for we…
Browse files Browse the repository at this point in the history
…bkitgtk apps
  • Loading branch information
olekolek1000 committed Jan 16, 2025
1 parent d8180bb commit 83026de
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 17 deletions.
44 changes: 43 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ khronos-egl = { version = "6.0.0", features = ["static"], optional = true }
smithay = { git = "https://github.com/Smithay/smithay.git", default-features = false, features = [
"renderer_gl",
"backend_egl",
"backend_drm",
"xwayland",
"wayland_frontend",
], optional = true }
Expand Down
32 changes: 30 additions & 2 deletions src/backend/wayvr/comp.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
use smithay::backend::allocator::dmabuf::Dmabuf;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::backend::renderer::utils::on_commit_buffer_handler;
use smithay::backend::renderer::ImportDma;
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::protocol::{wl_buffer, wl_seat, wl_surface};
use smithay::reexports::wayland_server::Resource;
use smithay::wayland::buffer::BufferHandler;
use smithay::wayland::dmabuf::{
DmabufFeedback, DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier,
};
use smithay::wayland::output::OutputHandler;
use smithay::wayland::shm::{ShmHandler, ShmState};
use smithay::{
delegate_compositor, delegate_data_device, delegate_output, delegate_seat, delegate_shm,
delegate_xdg_shell,
delegate_compositor, delegate_data_device, delegate_dmabuf, delegate_output, delegate_seat,
delegate_shm, delegate_xdg_shell,
};
use std::collections::HashSet;
use std::os::fd::OwnedFd;
Expand All @@ -34,6 +40,8 @@ use super::event_queue::SyncEventQueue;
use super::WayVRTask;

pub struct Application {
pub gles_renderer: GlesRenderer,
pub dmabuf_state: (DmabufState, DmabufGlobal, Option<DmabufFeedback>),
pub compositor: compositor::CompositorState,
pub xdg_shell: XdgShellState,
pub seat_state: SeatState<Application>,
Expand Down Expand Up @@ -172,6 +180,26 @@ impl ShmHandler for Application {

impl OutputHandler for Application {}

impl DmabufHandler for Application {
fn dmabuf_state(&mut self) -> &mut DmabufState {
&mut self.dmabuf_state.0
}

fn dmabuf_imported(
&mut self,
_global: &DmabufGlobal,
dmabuf: Dmabuf,
notifier: ImportNotifier,
) {
if self.gles_renderer.import_dmabuf(&dmabuf, None).is_ok() {
let _ = notifier.successful::<Application>();
} else {
notifier.failed();
}
}
}

delegate_dmabuf!(Application);
delegate_xdg_shell!(Application);
delegate_compositor!(Application);
delegate_shm!(Application);
Expand Down
78 changes: 64 additions & 14 deletions src/backend/wayvr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@ use process::ProcessVec;
use server_ipc::WayVRServer;
use smallvec::SmallVec;
use smithay::{
backend::renderer::gles::GlesRenderer,
backend::{
egl,
renderer::{gles::GlesRenderer, ImportDma},
},
input::SeatState,
output::{Mode, Output},
reexports::wayland_server::{self, backend::ClientId},
wayland::{
compositor,
dmabuf::{DmabufFeedbackBuilder, DmabufState},
selection::data_device::DataDeviceState,
shell::xdg::{ToplevelSurface, XdgShellState},
shm::ShmState,
Expand Down Expand Up @@ -81,7 +85,6 @@ pub struct Config {

pub struct WayVRState {
time_start: u64,
gles_renderer: GlesRenderer,
pub displays: display::DisplayVec,
pub manager: client::WayVRCompositor,
wm: Rc<RefCell<window::WindowManager>>,
Expand Down Expand Up @@ -143,9 +146,55 @@ impl WayVR {
size: (dummy_width, dummy_height).into(),
};

let _global = output.create_global::<Application>(&dh);
output.change_current_state(Some(mode), None, None, None);
output.set_preferred(mode);
let _global = output.create_global::<Application>(&dh);

let egl_data = egl_data::EGLData::new()?;

let smithay_display = smithay_wrapper::get_egl_display(&egl_data)?;
let smithay_context = smithay_wrapper::get_egl_context(&egl_data, &smithay_display)?;

let render_node = egl::EGLDevice::device_for_display(&smithay_display)
.and_then(|device| device.try_get_render_node());

let gles_renderer = unsafe { GlesRenderer::new(smithay_context)? };

let dmabuf_default_feedback = match render_node {
Ok(Some(node)) => {
let dmabuf_formats = gles_renderer.dmabuf_formats();
let dmabuf_default_feedback =
DmabufFeedbackBuilder::new(node.dev_id(), dmabuf_formats)
.build()
.unwrap();
Some(dmabuf_default_feedback)
}
Ok(None) => {
log::warn!("dmabuf: Failed to query render node");
debug_assert!(false);
None
}
Err(err) => {
log::warn!("dmabuf: Failed to get egl device for display: {}", err);
debug_assert!(false);
None
}
};

let dmabuf_state = if let Some(default_feedback) = dmabuf_default_feedback {
let mut dmabuf_state = DmabufState::new();
let dmabuf_global = dmabuf_state.create_global_with_default_feedback::<Application>(
&display.handle(),
&default_feedback,
);
(dmabuf_state, dmabuf_global, Some(default_feedback))
} else {
let dmabuf_formats = gles_renderer.dmabuf_formats();
let mut dmabuf_state = DmabufState::new();
let dmabuf_global =
dmabuf_state.create_global::<Application>(&display.handle(), dmabuf_formats);
(dmabuf_state, dmabuf_global, None)
};

let seat_keyboard = seat.add_keyboard(
Default::default(),
Expand All @@ -164,18 +213,15 @@ impl WayVR {
data_device,
wayvr_tasks: tasks.clone(),
redraw_requests: HashSet::new(),
dmabuf_state,
gles_renderer,
};

let time_start = get_millis();
let egl_data = egl_data::EGLData::new()?;
let smithay_display = smithay_wrapper::get_egl_display(&egl_data)?;
let smithay_context = smithay_wrapper::get_egl_context(&egl_data, &smithay_display)?;
let gles_renderer = unsafe { GlesRenderer::new(smithay_context)? };

let ipc_server = WayVRServer::new()?;

let state = WayVRState {
gles_renderer,
time_start,
manager: client::WayVRCompositor::new(state, display, seat_keyboard, seat_pointer)?,
displays: DisplayVec::new(),
Expand Down Expand Up @@ -214,7 +260,7 @@ impl WayVR {

let time_ms = get_millis() - self.state.time_start;

display.tick_render(&mut self.state.gles_renderer, time_ms)?;
display.tick_render(&mut self.state.manager.state.gles_renderer, time_ms)?;
display.wants_redraw = false;

Ok(())
Expand Down Expand Up @@ -316,10 +362,14 @@ impl WayVR {
}

pub fn tick_finish(&mut self) -> anyhow::Result<()> {
self.state.gles_renderer.with_context(|gl| unsafe {
gl.Flush();
gl.Finish();
})?;
self.state
.manager
.state
.gles_renderer
.with_context(|gl| unsafe {
gl.Flush();
gl.Finish();
})?;
Ok(())
}

Expand Down Expand Up @@ -404,7 +454,7 @@ impl WayVRState {
) -> anyhow::Result<display::DisplayHandle> {
let display = display::Display::new(
self.wm.clone(),
&mut self.gles_renderer,
&mut self.manager.state.gles_renderer,
self.egl_data.clone(),
self.manager.wayland_env.clone(),
width,
Expand Down

0 comments on commit 83026de

Please sign in to comment.