From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- third_party/rust/wgpu-core/src/any_surface.rs | 95 +++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 third_party/rust/wgpu-core/src/any_surface.rs (limited to 'third_party/rust/wgpu-core/src/any_surface.rs') diff --git a/third_party/rust/wgpu-core/src/any_surface.rs b/third_party/rust/wgpu-core/src/any_surface.rs new file mode 100644 index 0000000000..94edfc4433 --- /dev/null +++ b/third_party/rust/wgpu-core/src/any_surface.rs @@ -0,0 +1,95 @@ +use wgt::Backend; + +/// The `AnySurface` type: a `Arc` of a `A::Surface` for any backend `A`. +use crate::hal_api::HalApi; + +use std::fmt; +use std::mem::ManuallyDrop; +use std::ptr::NonNull; + +struct AnySurfaceVtable { + // We oppurtunistically store the backend here, since we now it will be used + // with backend selection and it can be stored in static memory. + backend: Backend, + // Drop glue which knows how to drop the stored data. + drop: unsafe fn(*mut ()), +} + +/// An `A::Surface`, for any backend `A`. +/// +/// Any `AnySurface` is just like an `A::Surface`, except that the `A` type +/// parameter is erased. To access the `Surface`, you must downcast to a +/// particular backend with the \[`downcast_ref`\] or \[`take`\] methods. +pub struct AnySurface { + data: NonNull<()>, + vtable: &'static AnySurfaceVtable, +} + +impl AnySurface { + /// Construct an `AnySurface` that owns an `A::Surface`. + pub fn new(surface: A::Surface) -> AnySurface { + unsafe fn drop_glue(ptr: *mut ()) { + unsafe { + _ = Box::from_raw(ptr.cast::()); + } + } + + let data = NonNull::from(Box::leak(Box::new(surface))); + + AnySurface { + data: data.cast(), + vtable: &AnySurfaceVtable { + backend: A::VARIANT, + drop: drop_glue::, + }, + } + } + + /// Get the backend this surface was created through. + pub fn backend(&self) -> Backend { + self.vtable.backend + } + + /// If `self` refers to an `A::Surface`, returns a reference to it. + pub fn downcast_ref(&self) -> Option<&A::Surface> { + if A::VARIANT != self.vtable.backend { + return None; + } + + // SAFETY: We just checked the instance above implicitly by the backend + // that it was statically constructed through. + Some(unsafe { &*self.data.as_ptr().cast::() }) + } + + /// If `self` is an `Arc`, returns that. + pub fn take(self) -> Option { + if A::VARIANT != self.vtable.backend { + return None; + } + + // Disable drop glue, since we're returning the owned surface. The + // caller will be responsible for dropping it. + let this = ManuallyDrop::new(self); + + // SAFETY: We just checked the instance above implicitly by the backend + // that it was statically constructed through. + Some(unsafe { *Box::from_raw(this.data.as_ptr().cast::()) }) + } +} + +impl Drop for AnySurface { + fn drop(&mut self) { + unsafe { (self.vtable.drop)(self.data.as_ptr()) } + } +} + +impl fmt::Debug for AnySurface { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "AnySurface<{}>", self.vtable.backend) + } +} + +#[cfg(send_sync)] +unsafe impl Send for AnySurface {} +#[cfg(send_sync)] +unsafe impl Sync for AnySurface {} -- cgit v1.2.3