summaryrefslogtreecommitdiffstats
path: root/third_party/rust/d3d12/src/com.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/d3d12/src/com.rs
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/d3d12/src/com.rs')
-rw-r--r--third_party/rust/d3d12/src/com.rs263
1 files changed, 263 insertions, 0 deletions
diff --git a/third_party/rust/d3d12/src/com.rs b/third_party/rust/d3d12/src/com.rs
new file mode 100644
index 0000000000..f3a85789ce
--- /dev/null
+++ b/third_party/rust/d3d12/src/com.rs
@@ -0,0 +1,263 @@
+use crate::D3DResult;
+use std::{
+ fmt,
+ hash::{Hash, Hasher},
+ ops::Deref,
+ ptr,
+};
+use winapi::{ctypes::c_void, um::unknwnbase::IUnknown, Interface};
+
+#[repr(transparent)]
+pub struct WeakPtr<T>(*mut T);
+
+impl<T> WeakPtr<T> {
+ pub fn null() -> Self {
+ WeakPtr(ptr::null_mut())
+ }
+
+ pub unsafe fn from_raw(raw: *mut T) -> Self {
+ WeakPtr(raw)
+ }
+
+ pub fn is_null(&self) -> bool {
+ self.0.is_null()
+ }
+
+ pub fn as_ptr(&self) -> *const T {
+ self.0
+ }
+
+ pub fn as_mut_ptr(&self) -> *mut T {
+ self.0
+ }
+
+ pub fn mut_void(&mut self) -> *mut *mut c_void {
+ &mut self.0 as *mut *mut _ as *mut *mut _
+ }
+
+ pub fn mut_self(&mut self) -> *mut *mut T {
+ &mut self.0 as *mut *mut _
+ }
+}
+
+impl<T: Interface> WeakPtr<T> {
+ pub unsafe fn as_unknown(&self) -> &IUnknown {
+ debug_assert!(!self.is_null());
+ &*(self.0 as *mut IUnknown)
+ }
+
+ // Cast creates a new WeakPtr requiring explicit destroy call.
+ pub unsafe fn cast<U>(&self) -> D3DResult<WeakPtr<U>>
+ where
+ U: Interface,
+ {
+ let mut obj = WeakPtr::<U>::null();
+ let hr = self
+ .as_unknown()
+ .QueryInterface(&U::uuidof(), obj.mut_void());
+ (obj, hr)
+ }
+
+ // Destroying one instance of the WeakPtr will invalidate all
+ // copies and clones.
+ pub unsafe fn destroy(&self) {
+ self.as_unknown().Release();
+ }
+}
+
+impl<T> Clone for WeakPtr<T> {
+ fn clone(&self) -> Self {
+ WeakPtr(self.0)
+ }
+}
+
+impl<T> Copy for WeakPtr<T> {}
+
+impl<T> Deref for WeakPtr<T> {
+ type Target = T;
+ fn deref(&self) -> &T {
+ debug_assert!(!self.is_null());
+ unsafe { &*self.0 }
+ }
+}
+
+impl<T> fmt::Debug for WeakPtr<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "WeakPtr( ptr: {:?} )", self.0)
+ }
+}
+
+impl<T> PartialEq<*mut T> for WeakPtr<T> {
+ fn eq(&self, other: &*mut T) -> bool {
+ self.0 == *other
+ }
+}
+
+impl<T> PartialEq for WeakPtr<T> {
+ fn eq(&self, other: &Self) -> bool {
+ self.0 == other.0
+ }
+}
+
+impl<T> Hash for WeakPtr<T> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.0.hash(state);
+ }
+}
+
+/// Macro that allows generation of an easy to use enum for dealing with many different possible versions of a COM object.
+///
+/// Give the variants so that parents come before children. This often manifests as going up in order (1 -> 2 -> 3). This is vital for safety.
+///
+/// Three function names need to be attached to each variant. The examples are given for the MyComObject1 variant below:
+/// - the from function (`WeakPtr<actual::ComObject1> -> Self`)
+/// - the as function (`&self -> Option<WeakPtr<actual::ComObject1>>`)
+/// - the unwrap function (`&self -> WeakPtr<actual::ComObject1>` panicing on failure to cast)
+///
+/// ```rust
+/// # pub use d3d12::weak_com_inheritance_chain;
+/// # mod actual {
+/// # pub struct ComObject; impl winapi::Interface for ComObject { fn uuidof() -> winapi::shared::guiddef::GUID { todo!() } }
+/// # pub struct ComObject1; impl winapi::Interface for ComObject1 { fn uuidof() -> winapi::shared::guiddef::GUID { todo!() } }
+/// # pub struct ComObject2; impl winapi::Interface for ComObject2 { fn uuidof() -> winapi::shared::guiddef::GUID { todo!() } }
+/// # }
+/// weak_com_inheritance_chain! {
+/// pub enum MyComObject {
+/// MyComObject(actual::ComObject), from_my_com_object, as_my_com_object, my_com_object; // First variant doesn't use "unwrap" as it can never fail
+/// MyComObject1(actual::ComObject1), from_my_com_object1, as_my_com_object1, unwrap_my_com_object1;
+/// MyComObject2(actual::ComObject2), from_my_com_object2, as_my_com_object2, unwrap_my_com_object2;
+/// }
+/// }
+/// ```
+#[macro_export]
+macro_rules! weak_com_inheritance_chain {
+ // We first match a human readable enum style, before going into the recursive section.
+ //
+ // Internal calls to the macro have either the prefix
+ // - @recursion_logic for the recursion and termination
+ // - @render_members for the actual call to fill in the members.
+ (
+ $(#[$meta:meta])*
+ $vis:vis enum $name:ident {
+ $first_variant:ident($first_type:ty), $first_from_name:ident, $first_as_name:ident, $first_unwrap_name:ident $(;)?
+ $($variant:ident($type:ty), $from_name:ident, $as_name:ident, $unwrap_name:ident);* $(;)?
+ }
+ ) => {
+ $(#[$meta])*
+ $vis enum $name {
+ $first_variant($crate::WeakPtr<$first_type>),
+ $(
+ $variant($crate::WeakPtr<$type>)
+ ),+
+ }
+ impl $name {
+ $vis unsafe fn destroy(&self) {
+ match *self {
+ Self::$first_variant(v) => v.destroy(),
+ $(
+ Self::$variant(v) => v.destroy(),
+ )*
+ }
+ }
+
+ $crate::weak_com_inheritance_chain! {
+ @recursion_logic,
+ $vis,
+ ;
+ $first_variant($first_type), $first_from_name, $first_as_name, $first_unwrap_name;
+ $($variant($type), $from_name, $as_name, $unwrap_name);*
+ }
+ }
+
+ impl std::ops::Deref for $name {
+ type Target = $crate::WeakPtr<$first_type>;
+ fn deref(&self) -> &Self::Target {
+ self.$first_unwrap_name()
+ }
+ }
+ };
+
+ // This is the iteration case of the recursion. We instantiate the member functions for the variant we
+ // are currently at, recursing on ourself for the next variant. Note we only keep track of the previous
+ // variant name, not the functions names, as those are not needed.
+ (
+ @recursion_logic,
+ $vis:vis,
+ $(,)? $($prev_variant:ident),* $(,)?;
+ $this_variant:ident($this_type:ty), $this_from_name:ident, $this_as_name:ident, $this_unwrap_name:ident $(;)?
+ $($next_variant:ident($next_type:ty), $next_from_name:ident, $next_as_name:ident, $next_unwrap_name:ident);*
+ ) => {
+ // Actually generate the members for this variant. Needs the previous and future variant names.
+ $crate::weak_com_inheritance_chain! {
+ @render_members,
+ $vis,
+ $this_from_name, $this_as_name, $this_unwrap_name;
+ $($prev_variant),*;
+ $this_variant($this_type);
+ $($next_variant),*;
+ }
+
+ // Recurse on ourselves. If there is no future variants left, we'll hit the base case as the final expansion returns no tokens.
+ $crate::weak_com_inheritance_chain! {
+ @recursion_logic,
+ $vis,
+ $($prev_variant),* , $this_variant;
+ $($next_variant($next_type), $next_from_name, $next_as_name, $next_unwrap_name);*
+ }
+ };
+ // Base case for recursion. There are no more variants left
+ (
+ @recursion_logic,
+ $vis:vis,
+ $($prev_variant:ident),*;
+ ) => {};
+
+
+ // This is where we generate the members using the given names.
+ (
+ @render_members,
+ $vis:vis,
+ $from_name:ident, $as_name:ident, $unwrap_name:ident;
+ $($prev_variant:ident),*;
+ $variant:ident($type:ty);
+ $($next_variant:ident),*;
+ ) => {
+ // Construct this enum from weak pointer to this interface. For best usability, always use the highest constructor you can. This doesn't try to upcast.
+ $vis unsafe fn $from_name(value: $crate::WeakPtr<$type>) -> Self {
+ Self::$variant(value)
+ }
+
+ // Returns Some if the value implements the interface otherwise returns None.
+ $vis fn $as_name(&self) -> Option<&$crate::WeakPtr<$type>> {
+ match *self {
+ $(
+ Self::$prev_variant(_) => None,
+ )*
+ Self::$variant(ref v) => Some(v),
+ $(
+ Self::$next_variant(ref v) => {
+ // v is &WeakPtr<NextType> and se cast to &WeakPtr<Type>
+ Some(unsafe { std::mem::transmute(v) })
+ }
+ )*
+ }
+ }
+
+ // Returns the interface if the value implements it, otherwise panics.
+ #[track_caller]
+ $vis fn $unwrap_name(&self) -> &$crate::WeakPtr<$type> {
+ match *self {
+ $(
+ Self::$prev_variant(_) => panic!(concat!("Tried to unwrap a ", stringify!($prev_variant), " as a ", stringify!($variant))),
+ )*
+ Self::$variant(ref v) => &*v,
+ $(
+ Self::$next_variant(ref v) => {
+ // v is &WeakPtr<NextType> and se cast to &WeakPtr<Type>
+ unsafe { std::mem::transmute(v) }
+ }
+ )*
+ }
+ }
+ };
+}