From 749a0325078d2c8f2b3c52d869e520745d1d4077 Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Wed, 16 Mar 2022 20:19:12 +0100 Subject: [PATCH] wayland: add wl_drm protocol --- Cargo.lock | 1 + Cargo.toml | 3 + build.rs | 19 +++- resources/wayland-drm.xml | 189 ++++++++++++++++++++++++++++++++++++++ src/main.rs | 1 + src/wayland/drm.rs | 106 +++++++++++++++++++++ src/wayland/mod.rs | 2 + 7 files changed, 320 insertions(+), 1 deletion(-) create mode 100644 resources/wayland-drm.xml create mode 100644 src/wayland/drm.rs create mode 100644 src/wayland/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 2a2ec00e..f7021483 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -299,6 +299,7 @@ dependencies = [ "smithay", "smithay-egui", "thiserror", + "wayland-scanner", "xcursor", ] diff --git a/Cargo.toml b/Cargo.toml index 781db15e..b9d031c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,9 @@ git = "https://github.com/Smithay/smithay-egui.git" rev = "5cc416ce" optional = true +[build-dependencies] +wayland-scanner = "0.29" + [features] default = [] debug = ["egui", "smithay-egui", "serde", "serde_json"] \ No newline at end of file diff --git a/build.rs b/build.rs index cc1fe41f..5c9234a8 100644 --- a/build.rs +++ b/build.rs @@ -1,6 +1,12 @@ // SPDX-License-Identifier: GPL-3.0-only +extern crate wayland_scanner; -use std::process::Command; +use wayland_scanner::{Side, generate_code}; +use std::{ + env, + process::Command, + path::PathBuf, +}; fn main() { if let Some(output) = Command::new("git") @@ -11,4 +17,15 @@ fn main() { let git_hash = String::from_utf8(output.stdout).unwrap(); println!("cargo:rustc-env=GIT_HASH={}", git_hash); } + + + let dest = PathBuf::from(&env::var("OUT_DIR").unwrap()); + // Location of the xml file, relative to the `Cargo.toml` + let drm_protocol_file = "resources/wayland-drm.xml"; + // Target directory for the generate files + generate_code( + drm_protocol_file, + &dest.join("wl_drm.rs"), + Side::Server, + ); } diff --git a/resources/wayland-drm.xml b/resources/wayland-drm.xml new file mode 100644 index 00000000..eaf2654a --- /dev/null +++ b/resources/wayland-drm.xml @@ -0,0 +1,189 @@ + + + + + Copyright © 2008-2011 Kristian Høgsberg + Copyright © 2010-2011 Intel Corporation + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that\n the above copyright notice appear in + all copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + the copyright holders not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. The copyright holders make no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF + THIS SOFTWARE. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Bitmask of capabilities. + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main.rs b/src/main.rs index 9db8f8d0..2622918d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,6 +14,7 @@ mod logger; pub mod shell; pub mod state; pub mod utils; +pub mod wayland; #[cfg(feature = "debug")] pub mod debug; diff --git a/src/wayland/drm.rs b/src/wayland/drm.rs new file mode 100644 index 00000000..e116587e --- /dev/null +++ b/src/wayland/drm.rs @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: GPL-3.0-only + +// Re-export only the actual code, and then only use this re-export +// The `generated` module below is just some boilerplate to properly isolate stuff +// and avoid exposing internal details. +// +// You can use all the types from my_protocol as if they went from `wayland_client::protocol`. +pub use generated::server::wl_drm; + +mod generated { + // The generated code tends to trigger a lot of warnings + // so we isolate it into a very permissive module + #![allow(dead_code,non_camel_case_types,unused_unsafe,unused_variables)] + #![allow(non_upper_case_globals,non_snake_case,unused_imports)] + + pub mod server { + use smithay::reexports::{wayland_commons, wayland_server}; + + // These imports are used by the generated code + pub(crate) use wayland_server::{Main, AnonymousObject, Resource, ResourceMap}; + pub(crate) use wayland_commons::map::{Object, ObjectMetadata}; + pub(crate) use wayland_commons::{Interface, MessageGroup}; + pub(crate) use wayland_commons::wire::{Argument, MessageDesc, ArgumentType, Message}; + pub(crate) use wayland_commons::smallvec; + pub(crate) use wayland_server::sys; + pub(crate) use wayland_server::protocol::wl_buffer; + include!(concat!(env!("OUT_DIR"), "/wl_drm.rs")); + } +} + +use smithay::{ + backend::allocator::{ + Format, Fourcc, Modifier, + dmabuf::{Dmabuf, DmabufFlags}, + }, + reexports::wayland_server::{Client, Display, Filter, Global, Main}, +}; + +use std::{ + convert::TryFrom, + path::PathBuf, +}; + +pub fn init_wl_drm_global( + display: &mut Display, + device_path: PathBuf, + mut formats: Vec, + client_filter: F, +) -> Global +where + F: FnMut(Client) -> bool + 'static +{ + formats.dedup_by(|f1, f2| f1.code == f2.code); + let global = Filter::new(move |(drm, version): (Main, u32), _, _| { + drm.quick_assign(move |drm, req, _| { + match req { + wl_drm::Request::Authenticate { .. } => drm.authenticated(), + wl_drm::Request::CreateBuffer { id, .. } => { + id.as_ref().post_error(wl_drm::Error::InvalidName.to_raw(), String::from("Flink handles are unsupported, use PRIME")); + }, + wl_drm::Request::CreatePlanarBuffer { id, .. } => { + id.as_ref().post_error(wl_drm::Error::InvalidName.to_raw(), String::from("Flink handles are unsupported, use PRIME")); + }, + wl_drm::Request::CreatePrimeBuffer { + id, + name, + width, + height, + format, + offset0, + stride0, + .. + } => { + let format = match Fourcc::try_from(format) { + Ok(format) => format, + Err(_) => { + id.as_ref().post_error(wl_drm::Error::InvalidFormat.to_raw(), String::from("Format not advertised by wl_drm")); + return; + } + }; + + if width < 1 || height < 1 { + id.as_ref().post_error(wl_drm::Error::InvalidFormat.to_raw(), String::from("width or height not positive")); + return; + } + + let mut dma = Dmabuf::builder((width, height), format, DmabufFlags::empty()); + dma.add_plane(name, 0, offset0 as u32, stride0 as u32, Modifier::Invalid); + id.as_ref().user_data().set_threadsafe(|| dma.build().unwrap()); + id.quick_assign(|_, _, _| {}); + slog_scope::trace!("Created a new validated dma wl_buffer via wl_drm."); + }, + } + }); + drm.device(device_path.to_string_lossy().into_owned()); + if version >= 2 { + drm.capabilities(wl_drm::Capability::Prime.to_raw()); + } + for format in &formats { + if let Some(converted) = wl_drm::Format::from_raw(format.code as u32) { + drm.format(converted.to_raw()); + } + } + }); + display.create_global_with_filter(2, global, client_filter) +} \ No newline at end of file diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs new file mode 100644 index 00000000..6b8245ed --- /dev/null +++ b/src/wayland/mod.rs @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: GPL-3.0-only +pub mod drm; \ No newline at end of file