From 7a10a089720f63379f0412cea149fda565bcd545 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Fri, 25 Jul 2025 14:43:17 +0200 Subject: [PATCH 1/4] CI: Downgrade `fdeflate` and `flate2` crates to MSRV-compatible versions --- .github/workflows/ci.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ebcfdc0..713178c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,8 +80,11 @@ jobs: components: clippy default: true override: true - - name: Downgrade home - run: cargo update -p home --precise 0.5.5 + - name: Downgrade (transitive) dependencies + run: | + cargo update -p home --precise 0.5.5 + cargo update -p fdeflate --precise 0.3.5 + cargo update -p flate2 --precise 1.0.35 - name: Cargo cache uses: actions/cache@v3 with: From a63e4f626f6b22d3d9c7eb731a10b9824f5a85e8 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Wed, 5 Feb 2025 10:42:11 +0100 Subject: [PATCH 2/4] Fix new clippy lints up to Rust 1.88 Rust 1.84 points out new issues with improperly indented list items in doc comments, unnecessary named lifetimes, and missing types in transmutes (that can be circumvented entirely with helpers). Later, Rust 1.88 points out that variables can and should directly be referenced inside format strings for brevity and readability. --- drm-ffi/drm-sys/build.rs | 12 ++++++------ examples/atomic_modeset.rs | 8 ++++---- examples/ffi.rs | 10 +++++----- examples/kms_interactive.rs | 10 +++++----- examples/legacy_modeset.rs | 6 +++--- examples/properties.rs | 4 ++-- examples/resources.rs | 16 ++++++++-------- examples/utils/mod.rs | 2 +- src/buffer/mod.rs | 10 +++++----- src/control/dumbbuffer.rs | 2 +- src/control/mod.rs | 20 ++++++++++---------- src/control/plane.rs | 6 +++--- src/lib.rs | 2 +- 13 files changed, 54 insertions(+), 54 deletions(-) diff --git a/drm-ffi/drm-sys/build.rs b/drm-ffi/drm-sys/build.rs index 7f9b541..397ccf6 100644 --- a/drm-ffi/drm-sys/build.rs +++ b/drm-ffi/drm-sys/build.rs @@ -27,7 +27,7 @@ mod use_bindgen { } fn create_builder(contents: &str) -> Builder { - println!("{}", contents); + println!("{contents}"); let pkgconf = pkg_config::Config::new(); let include_paths = if let Ok(value) = var("LIBDRM_INCLUDE_PATH") { @@ -82,27 +82,27 @@ mod use_bindgen { // Create a name for a temporary value fn tmp_val(name: &str) -> String { - format!("{}{}", TMP_BIND_PREFIX, name) + format!("{TMP_BIND_PREFIX}{name}") } // Create a C include directive fn include(header: &str) -> String { - format!("#include <{}>", header) + format!("#include <{header}>") } // Create a C constant fn decl_const(ty: &str, name: &str, value: &str) -> String { - format!("const {} {} = {};", ty, name, value) + format!("const {ty} {name} = {value};") } // Create a C macro definition fn define_macro(name: &str, val: &str) -> String { - format!("#define {} {}", name, val) + format!("#define {name} {val}") } // Create a C undefinition fn undefine_macro(name: &str) -> String { - format!("#undef {}", name) + format!("#undef {name}") } // Rebind a C macro as a constant diff --git a/examples/atomic_modeset.rs b/examples/atomic_modeset.rs index 56000ee..cdf9dbc 100644 --- a/examples/atomic_modeset.rs +++ b/examples/atomic_modeset.rs @@ -98,10 +98,10 @@ pub fn main() { }); let plane = *better_planes.first().unwrap_or(&compatible_planes[0]); - println!("{:#?}", mode); - println!("{:#?}", fb); - println!("{:#?}", db); - println!("{:#?}", plane); + println!("{mode:#?}"); + println!("{fb:#?}"); + println!("{db:#?}"); + println!("{plane:#?}"); let con_props = card .get_properties(con.handle()) diff --git a/examples/ffi.rs b/examples/ffi.rs index bcff231..1e50514 100644 --- a/examples/ffi.rs +++ b/examples/ffi.rs @@ -30,12 +30,12 @@ impl Card { fn print_busid(fd: BorrowedFd<'_>) { let mut buffer = Vec::new(); let busid = ffi::get_bus_id(fd, Some(&mut buffer)); - println!("{:#?}", busid); + println!("{busid:#?}"); } fn print_client(fd: BorrowedFd<'_>) { let client = ffi::get_client(fd, 0); - println!("{:#?}", client); + println!("{client:#?}"); } fn print_version(fd: BorrowedFd<'_>) { @@ -45,14 +45,14 @@ fn print_version(fd: BorrowedFd<'_>) { let version = ffi::get_version(fd, Some(&mut name), Some(&mut date), Some(&mut desc)); - println!("{:#?}", version); + println!("{version:#?}"); } fn print_capabilities(fd: BorrowedFd<'_>) { for cty in 1.. { let cap = ffi::get_capability(fd, cty); match cap { - Ok(_) => println!("{:#?}", cap), + Ok(_) => println!("{cap:#?}"), Err(_) => break, } } @@ -60,7 +60,7 @@ fn print_capabilities(fd: BorrowedFd<'_>) { fn print_token(fd: BorrowedFd<'_>) { let token = ffi::auth::get_magic_token(fd); - println!("{:#?}", token); + println!("{token:#?}"); } fn main() { diff --git a/examples/kms_interactive.rs b/examples/kms_interactive.rs index 06c29d1..2cb96ee 100644 --- a/examples/kms_interactive.rs +++ b/examples/kms_interactive.rs @@ -9,7 +9,7 @@ pub fn main() { // Enable all possible client capabilities for &cap in capabilities::CLIENT_CAP_ENUMS { if let Err(e) = card.set_client_capability(cap, true) { - eprintln!("Unable to activate capability {:?}: {}", cap, e); + eprintln!("Unable to activate capability {cap:?}: {e}"); return; } } @@ -69,7 +69,7 @@ fn run_repl(card: &Card) { let args: Vec<_> = line.split_whitespace().collect(); match &args[..] { ["Quit"] => break, - args => println!("{:?}", args), + args => println!("{args:?}"), } } } @@ -78,7 +78,7 @@ fn run_repl(card: &Card) { let handle: u32 = str::parse(handle).unwrap(); let handle: drm::control::framebuffer::Handle = from_u32(handle).unwrap(); if let Err(err) = card.destroy_framebuffer(handle) { - println!("Unable to destroy framebuffer ({:?}): {}", handle, err); + println!("Unable to destroy framebuffer ({handle:?}): {err}"); } } // Print out all resources @@ -89,7 +89,7 @@ fn run_repl(card: &Card) { println!("\tCRTCS: {:?}", resources.crtcs()); println!("\tFramebuffers: {:?}", resources.framebuffers()); let planes = card.plane_handles().unwrap(); - println!("\tPlanes: {:?}", planes); + println!("\tPlanes: {planes:?}"); } // Print out the values of a specific property ["GetProperty", handle] => { @@ -112,7 +112,7 @@ fn run_repl(card: &Card) { HandleWithProperties::Plane(handle) => card.get_properties(handle).unwrap(), }; for (id, val) in props.iter() { - println!("\tProperty: {:?}\tValue: {:?}", id, val); + println!("\tProperty: {id:?}\tValue: {val:?}"); } } Err(_) => println!("Unknown handle or handle has no properties"), diff --git a/examples/legacy_modeset.rs b/examples/legacy_modeset.rs index 204e6d5..9bae694 100644 --- a/examples/legacy_modeset.rs +++ b/examples/legacy_modeset.rs @@ -64,9 +64,9 @@ pub fn main() { .add_framebuffer(&db, 24, 32) .expect("Could not create FB"); - println!("{:#?}", mode); - println!("{:#?}", fb); - println!("{:#?}", db); + println!("{mode:#?}"); + println!("{fb:#?}"); + println!("{db:#?}"); // Set the crtc // On many setups, this requires root access. diff --git a/examples/properties.rs b/examples/properties.rs index 83ffde3..1d5974b 100644 --- a/examples/properties.rs +++ b/examples/properties.rs @@ -6,7 +6,7 @@ fn print_properties(card: &Card, handle: T) { let props = card.get_properties(handle).unwrap(); for (&id, &val) in props.iter() { - println!("Property: {:?}", id); + println!("Property: {id:?}"); let info = card.get_property(id).unwrap(); println!("{:?}", info.name()); println!("{:#?}", info.value_type()); @@ -23,7 +23,7 @@ pub fn main() { // Enable all possible client capabilities for &cap in capabilities::CLIENT_CAP_ENUMS { if let Err(e) = card.set_client_capability(cap, true) { - eprintln!("Unable to activate capability {:?}: {}", cap, e); + eprintln!("Unable to activate capability {cap:?}: {e}"); return; } } diff --git a/examples/resources.rs b/examples/resources.rs index 0379c3f..159d529 100644 --- a/examples/resources.rs +++ b/examples/resources.rs @@ -8,7 +8,7 @@ pub fn main() { // Enable all possible client capabilities for &cap in capabilities::CLIENT_CAP_ENUMS { if let Err(e) = card.set_client_capability(cap, true) { - eprintln!("Unable to activate capability {:?}: {}", cap, e); + eprintln!("Unable to activate capability {cap:?}: {e}"); return; } } @@ -21,11 +21,11 @@ pub fn main() { println!("Encoders:\t{:?}", resources.encoders()); println!("CRTCs:\t\t{:?}", resources.crtcs()); println!("Framebuffers:\t{:?}", resources.framebuffers()); - println!("Planes:\t\t{:?}", plane_res); + println!("Planes:\t\t{plane_res:?}"); for &handle in resources.connectors() { let info = card.get_connector(handle, false).unwrap(); - println!("Connector: {:?}", handle); + println!("Connector: {handle:?}"); println!("\t{:?}-{}", info.interface(), info.interface_id()); println!("\t{:?}", info.state()); println!("\t{:?}", info.size()); @@ -33,14 +33,14 @@ pub fn main() { println!("\t{:?}", info.current_encoder()); for mode in card.get_modes(handle).unwrap() { - println!("{:?}", mode); + println!("{mode:?}"); } } println!("\n"); for &handle in resources.encoders() { let info = card.get_encoder(handle).unwrap(); - println!("Encoder: {:?}", handle); + println!("Encoder: {handle:?}"); println!("\t{:?}", info.kind()); println!("\t{:?}", info.crtc()); } @@ -48,7 +48,7 @@ pub fn main() { for &handle in resources.crtcs() { let info = card.get_crtc(handle).unwrap(); - println!("CRTC: {:?}", handle); + println!("CRTC: {handle:?}"); println!("\tPosition: {:?}", info.position()); println!("\tMode: {:?}", info.mode()); println!("\tFramebuffer: {:?}", info.framebuffer()); @@ -58,7 +58,7 @@ pub fn main() { for &handle in resources.framebuffers() { let info = card.get_framebuffer(handle).unwrap(); - println!("Framebuffer: {:?}", handle); + println!("Framebuffer: {handle:?}"); println!("\tSize: {:?}", info.size()); println!("\tPitch: {:?}", info.pitch()); println!("\tBPP: {:?}", info.bpp()); @@ -69,7 +69,7 @@ pub fn main() { for handle in plane_res { let info = card.get_plane(handle).unwrap(); - println!("Plane: {:?}", handle); + println!("Plane: {handle:?}"); println!("\tCRTC: {:?}", info.crtc()); println!("\tFramebuffer: {:?}", info.framebuffer()); println!("\tFormats: {:?}", info.formats()); diff --git a/examples/utils/mod.rs b/examples/utils/mod.rs index 2001fbe..9b904bc 100644 --- a/examples/utils/mod.rs +++ b/examples/utils/mod.rs @@ -60,7 +60,7 @@ pub mod images { use image; pub fn load_image(name: &str) -> image::RgbaImage { - let path = format!("examples/images/{}", name); + let path = format!("examples/images/{name}"); image::open(path).unwrap().to_rgba8() } } diff --git a/src/buffer/mod.rs b/src/buffer/mod.rs index 45de1b5..afca754 100644 --- a/src/buffer/mod.rs +++ b/src/buffer/mod.rs @@ -16,13 +16,13 @@ //! There are two methods of sharing a GEM handle between processes: //! //! 1. Using `Flink` to globally publish a handle using a 32-bit 'name'. This -//! requires either holding the DRM Master lock or having the process' -//! [`AuthToken`](struct@crate::AuthToken) authenticated. However, any process can -//! open these handles if they know (or even guess) the global name. +//! requires either holding the DRM Master lock or having the process' +//! [`AuthToken`](struct@crate::AuthToken) authenticated. However, any process can +//! open these handles if they know (or even guess) the global name. //! //! 2. Converting the GEM handle into a PRIME file descriptor, and passing it -//! like a regular one. This allows better control and security, and is the -//! recommended method of sharing buffers. +//! like a regular one. This allows better control and security, and is the +//! recommended method of sharing buffers. use crate::control; pub use drm_fourcc::{DrmFourcc, DrmModifier, DrmVendor, UnrecognizedFourcc, UnrecognizedVendor}; diff --git a/src/control/dumbbuffer.rs b/src/control/dumbbuffer.rs index d4a7ada..07c6644 100644 --- a/src/control/dumbbuffer.rs +++ b/src/control/dumbbuffer.rs @@ -63,7 +63,7 @@ impl DerefMut for DumbMapping<'_> { } } -impl<'a> Drop for DumbMapping<'a> { +impl Drop for DumbMapping<'_> { fn drop(&mut self) { unsafe { rustix::mm::munmap(self.map.as_mut_ptr() as *mut _, self.map.len()) diff --git a/src/control/mod.rs b/src/control/mod.rs index d9ae1c4..5004e1b 100644 --- a/src/control/mod.rs +++ b/src/control/mod.rs @@ -6,20 +6,20 @@ //! exposing the following resource types: //! //! * FrameBuffer - Specific to an individual process, these wrap around generic -//! GPU buffers so that they can be attached to a Plane. +//! GPU buffers so that they can be attached to a Plane. //! //! * Planes - Dedicated memory objects which contain a buffer that can then be -//! scanned out by a CRTC. There exist a few different types of planes depending -//! on the use case. +//! scanned out by a CRTC. There exist a few different types of planes depending +//! on the use case. //! //! * CRTC - Scanout engines that read pixel data from a Plane and sends it to -//! a Connector. Each CRTC has at least one Primary Plane. +//! a Connector. Each CRTC has at least one Primary Plane. //! //! * Connector - Represents the physical output, such as a DisplayPort or -//! VGA connector. +//! VGA connector. //! //! * Encoder - Encodes pixel data from a CRTC into something a Connector can -//! understand. +//! understand. //! //! Further details on each resource can be found in their respective modules. //! @@ -96,8 +96,8 @@ pub enum GetPlanarFramebufferError { impl fmt::Display for GetPlanarFramebufferError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Self::Io(err) => write!(f, "{}", err), - Self::UnrecognizedFourcc(err) => write!(f, "{}", err), + Self::Io(err) => write!(f, "{err}"), + Self::UnrecognizedFourcc(err) => write!(f, "{err}"), } } } @@ -214,7 +214,7 @@ pub trait Device: super::Device { }, modes: Mode::wrap_vec(modes), encoders: unsafe { transmute_vec_from_u32(encoders) }, - curr_enc: unsafe { mem::transmute(ffi_info.encoder_id) }, + curr_enc: from_u32(ffi_info.encoder_id), subpixel: connector::SubPixel::from_raw(ffi_info.subpixel), }; @@ -1567,7 +1567,7 @@ bitflags::bitflags! { /// the [`Self::ATOMIC`] flag is used to hide properties from userspace that /// is not aware of atomic properties. This is mostly to work around /// older userspace (DDX drivers) that read/write each prop they find, - /// witout being aware that this could be triggering a lengthy modeset. + /// without being aware that this could be triggering a lengthy modeset. const ATOMIC = ffi::DRM_MODE_PROP_ATOMIC; } } diff --git a/src/control/plane.rs b/src/control/plane.rs index 3637d94..425e01f 100644 --- a/src/control/plane.rs +++ b/src/control/plane.rs @@ -7,13 +7,13 @@ //! types of planes available for use: //! //! * Primary - A CRTC's built-in plane. When attaching a framebuffer to a CRTC, -//! it is actually being attached to this kind of plane. +//! it is actually being attached to this kind of plane. //! //! * Overlay - Can be overlaid on top of a primary plane, utilizing extremely -//! fast hardware compositing. +//! fast hardware compositing. //! //! * Cursor - Similar to an overlay plane, these are typically used to display -//! cursor type objects. +//! cursor type objects. use crate::control; use drm_ffi as ffi; diff --git a/src/lib.rs b/src/lib.rs index 1cee3f0..35860b9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -331,7 +331,7 @@ pub enum ClientCapability { /// cursor and have correctly set hotspot properties. /// If this client cap is not set the DRM core will hide cursor plane on /// those virtualized drivers because not setting it implies that the - /// client is not capable of dealing with those extra restictions. + /// client is not capable of dealing with those extra restrictions. /// Clients which do set cursor hotspot and treat the cursor plane /// like a mouse cursor should set this property. /// From 62ba9ffa289339432ee232c0fa791ae2c22344c3 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Fri, 25 Jul 2025 14:53:06 +0200 Subject: [PATCH 3/4] drm-ffi: Regenerate bindings against latest kernel headers This introduces a `point` variable on `drm_syncobj_handle` to import or export a `sync_file` at the given `point` on the `TIMELINE` of a `drm_syncobj`. --- drm-ffi/drm-sys/src/bindings.rs | 12 +++++++++++- drm-ffi/src/syncobj.rs | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drm-ffi/drm-sys/src/bindings.rs b/drm-ffi/drm-sys/src/bindings.rs index 9143a0e..b5018eb 100644 --- a/drm-ffi/drm-sys/src/bindings.rs +++ b/drm-ffi/drm-sys/src/bindings.rs @@ -1,4 +1,4 @@ -/* automatically generated by rust-bindgen 0.69.4 */ +/* automatically generated by rust-bindgen 0.69.5 */ pub const DRM_NAME: &[u8; 4] = b"drm\0"; pub const DRM_MIN_ORDER: u32 = 5; @@ -34,7 +34,9 @@ pub const DRM_CLIENT_CAP_WRITEBACK_CONNECTORS: u32 = 5; pub const DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT: u32 = 6; pub const DRM_SYNCOBJ_CREATE_SIGNALED: u32 = 1; pub const DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE: u32 = 1; +pub const DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE: u32 = 2; pub const DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE: u32 = 1; +pub const DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_TIMELINE: u32 = 2; pub const DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL: u32 = 1; pub const DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT: u32 = 2; pub const DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE: u32 = 4; @@ -42,6 +44,7 @@ pub const DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE: u32 = 8; pub const DRM_SYNCOBJ_QUERY_FLAGS_LAST_SUBMITTED: u32 = 1; pub const DRM_CRTC_SEQUENCE_RELATIVE: u32 = 1; pub const DRM_CRTC_SEQUENCE_NEXT_ON_MISS: u32 = 2; +pub const DRM_CLIENT_NAME_MAX_LEN: u32 = 64; pub const DRM_CONNECTOR_NAME_LEN: u32 = 32; pub const DRM_DISPLAY_MODE_LEN: u32 = 32; pub const DRM_PROP_NAME_LEN: u32 = 32; @@ -822,6 +825,7 @@ pub struct drm_syncobj_handle { pub flags: __u32, pub fd: __s32, pub pad: __u32, + pub point: __u64, } #[repr(C)] #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] @@ -898,6 +902,12 @@ pub struct drm_crtc_queue_sequence { } #[repr(C)] #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +pub struct drm_set_client_name { + pub name_len: __u64, + pub name: __u64, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] pub struct drm_mode_modeinfo { pub clock: __u32, pub hdisplay: __u16, diff --git a/drm-ffi/src/syncobj.rs b/drm-ffi/src/syncobj.rs index 5334944..1310e78 100644 --- a/drm-ffi/src/syncobj.rs +++ b/drm-ffi/src/syncobj.rs @@ -54,6 +54,7 @@ pub fn handle_to_fd( }, fd: 0, pad: 0, + point: 0, // TODO: Add support for TIMELINE sync files }; unsafe { @@ -78,6 +79,7 @@ pub fn fd_to_handle( }, fd: syncobj_fd.as_raw_fd(), pad: 0, + point: 0, // TODO: Add support for TIMELINE sync files }; unsafe { From 6dee04a4128869781b051b353a33bf3e0dce7ef4 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Fri, 25 Jul 2025 15:42:48 +0200 Subject: [PATCH 4/4] CI: Bump `download/upload-artifact` to `v4` with merging on download https://github.blog/changelog/2024-04-16-deprecation-notice-v3-of-the-artifact-actions/ https://github.com/actions/upload-artifact/blob/main/docs/MIGRATION.md#multiple-uploads-to-the-same-named-artifact --- .github/workflows/ci.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 713178c..332e0d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -237,9 +237,9 @@ jobs: run: cp drm-ffi/drm-sys/src/bindings.rs bindings-${{ matrix.target }}.rs - name: Upload bindings if: matrix.task == 'bindings' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: bindings + name: bindings-${{ matrix.target }}-${{ matrix.rust }} path: bindings-*.rs - name: Build uses: actions-rs/cargo@v1 @@ -262,9 +262,10 @@ jobs: runs-on: ubuntu-22.04 steps: - name: download bindings - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: - name: bindings + pattern: bindings-* + merge-multiple: true - name: compare run: | code=0 @@ -289,9 +290,10 @@ jobs: steps: - uses: actions/checkout@v3 - name: download bindings - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: - name: bindings + pattern: bindings-* + merge-multiple: true - name: Copy x86_64 bindings run: | cp bindings-x86_64-unknown-linux-gnu.rs drm-ffi/drm-sys/src/bindings.rs