|
1 | 1 | #![allow(clippy::let_unit_value)] // `let () =` being used to constrain result type
|
2 | 2 |
|
3 | 3 | use alloc::borrow::ToOwned as _;
|
4 |
| -use core::mem::ManuallyDrop; |
5 | 4 | use core::ptr::NonNull;
|
| 5 | +use core::{ffi::c_void, mem::ManuallyDrop}; |
6 | 6 | use std::thread;
|
7 | 7 |
|
8 | 8 | use core_graphics_types::{
|
@@ -34,20 +34,57 @@ impl super::Surface {
|
34 | 34 | }
|
35 | 35 | }
|
36 | 36 |
|
37 |
| - /// If not called on the main thread, this will panic. |
38 |
| - #[allow(clippy::transmute_ptr_to_ref)] |
39 |
| - pub unsafe fn from_view(view: NonNull<Object>) -> Self { |
40 |
| - let layer = unsafe { Self::get_metal_layer(view) }; |
| 37 | + /// Construct a surface from a pointer to a `NSView`. |
| 38 | + /// |
| 39 | + /// # Panics |
| 40 | + /// |
| 41 | + /// Panics if called from a thread that is not the main thread. |
| 42 | + /// |
| 43 | + /// # Safety |
| 44 | + /// |
| 45 | + /// The given view pointer must be a valid instance of `NSView`. |
| 46 | + pub unsafe fn from_ns_view(view: NonNull<c_void>) -> Self { |
| 47 | + // SAFETY: Upheld by caller. |
| 48 | + let layer = unsafe { Self::get_metal_layer(view.cast()) }; |
41 | 49 | let layer = ManuallyDrop::new(layer);
|
42 | 50 | // SAFETY: The layer is an initialized instance of `CAMetalLayer`, and
|
43 | 51 | // we transfer the retain count to `MetalLayer` using `ManuallyDrop`.
|
44 | 52 | let layer = unsafe { metal::MetalLayer::from_ptr(layer.cast()) };
|
45 | 53 | Self::new(layer)
|
46 | 54 | }
|
47 | 55 |
|
48 |
| - pub unsafe fn from_layer(layer: &metal::MetalLayerRef) -> Self { |
| 56 | + /// Construct a surface from a pointer to a `UIView`. |
| 57 | + /// |
| 58 | + /// # Panics |
| 59 | + /// |
| 60 | + /// Panics if called from a thread that is not the main thread. |
| 61 | + /// |
| 62 | + /// # Safety |
| 63 | + /// |
| 64 | + /// The given view pointer must be a valid instance of `UIView`. |
| 65 | + pub unsafe fn from_ui_view(view: NonNull<c_void>) -> Self { |
| 66 | + // SAFETY: Upheld by caller. |
| 67 | + let layer = unsafe { Self::get_metal_layer(view.cast()) }; |
| 68 | + let layer = ManuallyDrop::new(layer); |
| 69 | + // SAFETY: The layer is an initialized instance of `CAMetalLayer`, and |
| 70 | + // we transfer the retain count to `MetalLayer` using `ManuallyDrop`. |
| 71 | + let layer = unsafe { metal::MetalLayer::from_ptr(layer.cast()) }; |
| 72 | + Self::new(layer) |
| 73 | + } |
| 74 | + |
| 75 | + /// Construct a surface from a pointer to a `CAMetalLayer`. |
| 76 | + /// |
| 77 | + /// # Safety |
| 78 | + /// |
| 79 | + /// The given view pointer must be a valid instance of `CAMetalLayer`. |
| 80 | + pub unsafe fn from_layer(layer: NonNull<c_void>) -> Self { |
| 81 | + // SAFETY: Validity of the pointer is upheld by the caller. |
| 82 | + // |
| 83 | + // We extend the lifetime of the layer with `to_owned` below. |
| 84 | + let layer = unsafe { layer.cast::<metal::MetalLayerRef>().as_ref() }; |
| 85 | + |
49 | 86 | let class = class!(CAMetalLayer);
|
50 |
| - let proper_kind: BOOL = msg_send![layer, isKindOfClass: class]; |
| 87 | + let proper_kind: BOOL = unsafe { msg_send![layer, isKindOfClass: class] }; |
51 | 88 | assert_eq!(proper_kind, YES);
|
52 | 89 | Self::new(layer.to_owned())
|
53 | 90 | }
|
|
0 commit comments