mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
metal | vulkan-portability: extract the generic code into get_metal_layer (#2826)
This commit is contained in:
parent
a108efe6b6
commit
ecf3f5ec38
@ -70,6 +70,11 @@ Bottom level categories:
|
|||||||
|
|
||||||
- Document safety requirements for `Adapter::from_external` in gles hal by @i509VCB in [#2863](https://github.com/gfx-rs/wgpu/pull/2863)
|
- Document safety requirements for `Adapter::from_external` in gles hal by @i509VCB in [#2863](https://github.com/gfx-rs/wgpu/pull/2863)
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
#### Metal
|
||||||
|
- Extract the generic code into `get_metal_layer` by @jinleili in [#2826](https://github.com/gfx-rs/wgpu/pull/2826)
|
||||||
|
|
||||||
## wgpu-0.13.1 (2022-07-02)
|
## wgpu-0.13.1 (2022-07-02)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@ -81,30 +81,48 @@ impl super::Surface {
|
|||||||
delegate: Option<&HalManagedMetalLayerDelegate>,
|
delegate: Option<&HalManagedMetalLayerDelegate>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let view = view as *mut Object;
|
let view = view as *mut Object;
|
||||||
|
let render_layer =
|
||||||
|
mem::transmute::<_, &mtl::MetalLayerRef>(Self::get_metal_layer(view, delegate))
|
||||||
|
.to_owned();
|
||||||
|
Self::new(NonNull::new(view), render_layer)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn from_layer(layer: &mtl::MetalLayerRef) -> Self {
|
||||||
|
let class = class!(CAMetalLayer);
|
||||||
|
let proper_kind: BOOL = msg_send![layer, isKindOfClass: class];
|
||||||
|
assert_eq!(proper_kind, YES);
|
||||||
|
Self::new(None, layer.to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If not called on the main thread, this will panic.
|
||||||
|
pub unsafe fn get_metal_layer(
|
||||||
|
view: *mut Object,
|
||||||
|
delegate: Option<&HalManagedMetalLayerDelegate>,
|
||||||
|
) -> *mut Object {
|
||||||
if view.is_null() {
|
if view.is_null() {
|
||||||
panic!("window does not have a valid contentView");
|
panic!("window does not have a valid contentView");
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_main_thread: BOOL = msg_send![class!(NSThread), isMainThread];
|
let is_main_thread: BOOL = msg_send![class!(NSThread), isMainThread];
|
||||||
if is_main_thread == NO {
|
if is_main_thread == NO {
|
||||||
panic!("create_surface cannot be called in non-ui thread.");
|
panic!("get_metal_layer cannot be called in non-ui thread.");
|
||||||
}
|
}
|
||||||
|
|
||||||
let main_layer: *mut Object = msg_send![view, layer];
|
let main_layer: *mut Object = msg_send![view, layer];
|
||||||
let class = class!(CAMetalLayer);
|
let class = class!(CAMetalLayer);
|
||||||
let is_valid_layer: BOOL = msg_send![main_layer, isKindOfClass: class];
|
let is_valid_layer: BOOL = msg_send![main_layer, isKindOfClass: class];
|
||||||
|
|
||||||
let render_layer = if is_valid_layer == YES {
|
if is_valid_layer == YES {
|
||||||
mem::transmute::<_, &mtl::MetalLayerRef>(main_layer).to_owned()
|
main_layer
|
||||||
} else {
|
} else {
|
||||||
// If the main layer is not a CAMetalLayer, we create a CAMetalLayer and use it.
|
// If the main layer is not a CAMetalLayer, we create a CAMetalLayer and use it.
|
||||||
let new_layer: mtl::MetalLayer = msg_send![class, new];
|
let new_layer: *mut Object = msg_send![class, new];
|
||||||
let frame: CGRect = msg_send![main_layer, bounds];
|
let frame: CGRect = msg_send![main_layer, bounds];
|
||||||
let () = msg_send![new_layer.as_ref(), setFrame: frame];
|
let () = msg_send![new_layer, setFrame: frame];
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
{
|
{
|
||||||
// Unlike NSView, UIView does not allow to replace main layer.
|
// Unlike NSView, UIView does not allow to replace main layer.
|
||||||
let () = msg_send![main_layer, addSublayer: new_layer.as_ref()];
|
let () = msg_send![main_layer, addSublayer: new_layer];
|
||||||
// On iOS, "from_view" may be called before the application initialization is complete,
|
// On iOS, "from_view" may be called before the application initialization is complete,
|
||||||
// `msg_send![view, window]` and `msg_send![window, screen]` will get null.
|
// `msg_send![view, window]` and `msg_send![window, screen]` will get null.
|
||||||
let screen: *mut Object = msg_send![class!(UIScreen), mainScreen];
|
let screen: *mut Object = msg_send![class!(UIScreen), mainScreen];
|
||||||
@ -113,9 +131,9 @@ impl super::Surface {
|
|||||||
};
|
};
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
{
|
{
|
||||||
let () = msg_send![view, setLayer: new_layer.as_ref()];
|
let () = msg_send![view, setLayer: new_layer];
|
||||||
let () = msg_send![view, setWantsLayer: YES];
|
let () = msg_send![view, setWantsLayer: YES];
|
||||||
let () = msg_send![new_layer.as_ref(), setContentsGravity: kCAGravityTopLeft];
|
let () = msg_send![new_layer, setContentsGravity: kCAGravityTopLeft];
|
||||||
let window: *mut Object = msg_send![view, window];
|
let window: *mut Object = msg_send![view, window];
|
||||||
if !window.is_null() {
|
if !window.is_null() {
|
||||||
let scale_factor: CGFloat = msg_send![window, backingScaleFactor];
|
let scale_factor: CGFloat = msg_send![window, backingScaleFactor];
|
||||||
@ -126,17 +144,7 @@ impl super::Surface {
|
|||||||
let () = msg_send![new_layer, setDelegate: delegate.0];
|
let () = msg_send![new_layer, setDelegate: delegate.0];
|
||||||
}
|
}
|
||||||
new_layer
|
new_layer
|
||||||
};
|
}
|
||||||
|
|
||||||
let _: *mut c_void = msg_send![view, retain];
|
|
||||||
Self::new(NonNull::new(view), render_layer)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn from_layer(layer: &mtl::MetalLayerRef) -> Self {
|
|
||||||
let class = class!(CAMetalLayer);
|
|
||||||
let proper_kind: BOOL = msg_send![layer, isKindOfClass: class];
|
|
||||||
assert_eq!(proper_kind, YES);
|
|
||||||
Self::new(None, layer.to_owned())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn dimensions(&self) -> wgt::Extent3d {
|
pub(super) fn dimensions(&self) -> wgt::Extent3d {
|
||||||
|
|||||||
@ -415,46 +415,8 @@ impl super::Instance {
|
|||||||
|
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
fn create_surface_from_view(&self, view: *mut c_void) -> super::Surface {
|
fn create_surface_from_view(&self, view: *mut c_void) -> super::Surface {
|
||||||
use core_graphics_types::{base::CGFloat, geometry::CGRect};
|
|
||||||
use objc::{
|
|
||||||
class, msg_send,
|
|
||||||
runtime::{Object, BOOL, YES},
|
|
||||||
sel, sel_impl,
|
|
||||||
};
|
|
||||||
|
|
||||||
let layer = unsafe {
|
let layer = unsafe {
|
||||||
let view = view as *mut Object;
|
crate::metal::Surface::get_metal_layer(view as *mut objc::runtime::Object, None)
|
||||||
let existing: *mut Object = msg_send![view, layer];
|
|
||||||
let class = class!(CAMetalLayer);
|
|
||||||
|
|
||||||
let use_current: BOOL = msg_send![existing, isKindOfClass: class];
|
|
||||||
if use_current == YES {
|
|
||||||
existing
|
|
||||||
} else {
|
|
||||||
let new_layer: *mut Object = msg_send![class, new];
|
|
||||||
let frame: CGRect = msg_send![existing, bounds];
|
|
||||||
let () = msg_send![new_layer, setFrame: frame];
|
|
||||||
|
|
||||||
let scale_factor: CGFloat = if cfg!(target_os = "ios") {
|
|
||||||
let () = msg_send![existing, addSublayer: new_layer];
|
|
||||||
// On iOS, `create_surface_from_view` may be called before the application initialization is complete,
|
|
||||||
// `msg_send![view, window]` and `msg_send![window, screen]` will get null.
|
|
||||||
let screen: *mut Object = msg_send![class!(UIScreen), mainScreen];
|
|
||||||
msg_send![screen, nativeScale]
|
|
||||||
} else {
|
|
||||||
let () = msg_send![view, setLayer: new_layer];
|
|
||||||
let () = msg_send![view, setWantsLayer: YES];
|
|
||||||
let window: *mut Object = msg_send![view, window];
|
|
||||||
if !window.is_null() {
|
|
||||||
msg_send![window, backingScaleFactor]
|
|
||||||
} else {
|
|
||||||
1.0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let () = msg_send![new_layer, setContentsScale: scale_factor];
|
|
||||||
|
|
||||||
new_layer
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let surface = {
|
let surface = {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user