WayVR: Add dmabuf (backend_drm) to the compositor. Fixes crash for webkitgtk apps
This commit is contained in:
@@ -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;
|
||||
@@ -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>,
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
@@ -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>>,
|
||||
@@ -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(),
|
||||
@@ -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(),
|
||||
@@ -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(())
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user