[PATCH v2 06/12] rust: drm: gem: Add OpaqueObject
Lyude Paul
lyude at redhat.com
Wed May 21 20:29:13 UTC 2025
In the future, we want to have the ability for a driver to have private gem
objects - or use gem objects across ffi boundaries that don't use our
driver's GEM object implementation. So, let's take some inspiration from
the KMS bindings I've been working on and introduce an OpaqueObject type.
This type can be used identically to a normal gem object, with the
exception that the private-data layout of the object is not known.
Signed-off-by: Lyude Paul <lyude at redhat.com>
---
rust/kernel/drm/gem/mod.rs | 61 +++++++++++++++++++++++++++++++++++---
1 file changed, 57 insertions(+), 4 deletions(-)
diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs
index f0029e6989ed6..aeec847b80aa7 100644
--- a/rust/kernel/drm/gem/mod.rs
+++ b/rust/kernel/drm/gem/mod.rs
@@ -6,13 +6,13 @@
use crate::{
alloc::flags::*,
- bindings, drm,
+ bindings, drm::{self, private::Sealed},
drm::driver::{AllocImpl, AllocOps},
error::{to_result, Result},
prelude::*,
types::{ARef, AlwaysRefCounted, Opaque},
};
-use core::{ops::Deref, ptr::NonNull};
+use core::{ops::Deref, ptr::NonNull, marker::PhantomData};
/// A type alias for retrieving a [`Driver`]s [`DriverFile`] implementation from its
/// [`DriverObject`] implementation.
@@ -21,6 +21,26 @@
/// [`DriverFile`]: drm::file::DriverFile
pub type DriverFile<T> = drm::File<<<T as BaseDriverObject>::Driver as drm::Driver>::File>;
+/// A helper macro for implementing AsRef<OpaqueObject<…>>
+macro_rules! impl_as_opaque {
+ ($type:ty where $tparam:ident : $tparam_trait:ident) => {
+ impl<D, $tparam> core::convert::AsRef<kernel::drm::gem::OpaqueObject<D>> for $type
+ where
+ D: kernel::drm::driver::Driver,
+ Self: kernel::drm::gem::BaseDriverObject<Driver = D>,
+ Self: kernel::drm::gem::IntoGEMObject,
+ $tparam: $tparam_trait
+ {
+ fn as_ref(&self) -> &kernel::drm::gem::OpaqueObject<D> {
+ // SAFETY: This cast is safe via our type invariant.
+ unsafe { &*((self.as_raw().cast_const()).cast()) }
+ }
+ }
+ };
+}
+
+pub(crate) use impl_as_opaque;
+
/// GEM object functions, which must be implemented by drivers.
pub trait BaseDriverObject: Sync + Send + Sized {
/// Parent `Driver` for this object.
@@ -49,7 +69,7 @@ fn close(_obj: &Self::Object, _file: &DriverFile<Self>) {}
}
/// Trait that represents a GEM object subtype
-pub trait IntoGEMObject: Sized + super::private::Sealed + AlwaysRefCounted {
+pub trait IntoGEMObject: Sized + Sealed + AlwaysRefCounted {
/// Returns a reference to the raw `drm_gem_object` structure, which must be valid as long as
/// this owning object is valid.
fn as_raw(&self) -> *mut bindings::drm_gem_object;
@@ -297,7 +317,7 @@ extern "C" fn free_callback(obj: *mut bindings::drm_gem_object) {
}
}
-impl<T: BaseDriverObject> super::private::Sealed for Object<T> {}
+impl<T: BaseDriverObject> Sealed for Object<T> {}
impl<T: BaseDriverObject> Deref for Object<T> {
type Target = T;
@@ -321,6 +341,39 @@ impl<T: BaseDriverObject> AllocImpl for Object<T> {
};
}
+impl_as_opaque!(Object<T> where T: BaseDriverObject);
+
+/// A GEM object whose private-data layout is not known.
+///
+/// Not all GEM objects are created equal, and subsequently drivers may occasionally need to deal
+/// with situations where they are working with a GEM object but have no knowledge of its
+/// private-data layout.
+///
+/// It may be used just like a normal [`Object`], with the exception that it cannot access
+/// driver-private data.
+///
+/// # Invariant
+///
+/// Via `#[repr(transparent)]`, this type is guaranteed to have an identical data layout to
+/// `struct drm_gem_object`.
+#[repr(transparent)]
+pub struct OpaqueObject<T: drm::Driver>(Opaque<bindings::drm_gem_object>, PhantomData<T>);
+
+impl<T: drm::Driver> IntoGEMObject for OpaqueObject<T> {
+ unsafe fn as_ref<'a>(self_ptr: *mut bindings::drm_gem_object) -> &'a Self {
+ // SAFETY:
+ // - This cast is safe via our type invariant.
+ // - `self_ptr` is guaranteed to be a valid pointer to a gem object by our safety contract.
+ unsafe { &*self_ptr.cast::<Self>().cast_const() }
+ }
+
+ fn as_raw(&self) -> *mut bindings::drm_gem_object {
+ self.0.get()
+ }
+}
+
+impl<D: drm::Driver> Sealed for OpaqueObject<D> {}
+
pub(super) const fn create_fops() -> bindings::file_operations {
// SAFETY: As by the type invariant, it is safe to initialize `bindings::file_operations`
// zeroed.
--
2.49.0
More information about the dri-devel
mailing list