diff --git a/Cargo.lock b/Cargo.lock index dbe5e0e..2eca8e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1380,12 +1380,46 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" +[[package]] +name = "drm" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80bc8c5c6c2941f70a55c15f8d9f00f9710ebda3ffda98075f996a0e6c92756f" +dependencies = [ + "bitflags 2.6.0", + "bytemuck", + "drm-ffi", + "drm-fourcc", + "libc", + "rustix", +] + +[[package]] +name = "drm-ffi" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8e41459d99a9b529845f6d2c909eb9adf3b6d2f82635ae40be8de0601726e8b" +dependencies = [ + "drm-sys", + "rustix", +] + [[package]] name = "drm-fourcc" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4" +[[package]] +name = "drm-sys" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bafb66c8dbc944d69e15cfcc661df7e703beffbaec8bd63151368b06c5f9858c" +dependencies = [ + "libc", + "linux-raw-sys 0.6.5", +] + [[package]] name = "either" version = "1.13.0" @@ -2401,6 +2435,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "linux-raw-sys" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a385b1be4e5c3e362ad2ffa73c392e53f031eaa5b7d648e64cd87f27f6063d7" + [[package]] name = "litemap" version = "0.7.4" @@ -3546,7 +3586,7 @@ dependencies = [ "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.14", "windows-sys 0.52.0", ] @@ -3772,6 +3812,8 @@ dependencies = [ "cgmath", "cursor-icon", "downcast-rs", + "drm", + "drm-ffi", "drm-fourcc", "encoding_rs", "errno", diff --git a/Cargo.toml b/Cargo.toml index a5c5c4f..d117752 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 } diff --git a/src/backend/wayvr/comp.rs b/src/backend/wayvr/comp.rs index 5e0e236..1b07031 100644 --- a/src/backend/wayvr/comp.rs +++ b/src/backend/wayvr/comp.rs @@ -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), pub compositor: compositor::CompositorState, pub xdg_shell: XdgShellState, pub seat_state: SeatState, @@ -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::(); + } else { + notifier.failed(); + } + } +} + +delegate_dmabuf!(Application); delegate_xdg_shell!(Application); delegate_compositor!(Application); delegate_shm!(Application); diff --git a/src/backend/wayvr/mod.rs b/src/backend/wayvr/mod.rs index 1bd91c8..b5395c5 100644 --- a/src/backend/wayvr/mod.rs +++ b/src/backend/wayvr/mod.rs @@ -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>, @@ -143,9 +146,55 @@ impl WayVR { size: (dummy_width, dummy_height).into(), }; + let _global = output.create_global::(&dh); output.change_current_state(Some(mode), None, None, None); output.set_preferred(mode); - let _global = output.create_global::(&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::( + &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::(&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 { 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,