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