Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

metal | vulkan-portability: extract the generic code into get_metal_layer #2826

Merged
merged 2 commits into from
Jul 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ Bottom level categories:
#### DX12
- `DownlevelCapabilities::default()` now returns the `ANISOTROPIC_FILTERING` flag set to true so DX12 lists `ANISOTROPIC_FILTERING` as true again by @cwfitzgerald in [#2851](https://github.com/gfx-rs/wgpu/pull/2851)

### 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)

### Bug Fixes
Expand Down
46 changes: 27 additions & 19 deletions wgpu-hal/src/metal/surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,30 +81,48 @@ impl super::Surface {
delegate: Option<&HalManagedMetalLayerDelegate>,
) -> Self {
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() {
panic!("window does not have a valid contentView");
}

let is_main_thread: BOOL = msg_send![class!(NSThread), isMainThread];
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 class = class!(CAMetalLayer);
let is_valid_layer: BOOL = msg_send![main_layer, isKindOfClass: class];

let render_layer = if is_valid_layer == YES {
mem::transmute::<_, &mtl::MetalLayerRef>(main_layer).to_owned()
if is_valid_layer == YES {
main_layer
} else {
// 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 () = msg_send![new_layer.as_ref(), setFrame: frame];
let () = msg_send![new_layer, setFrame: frame];
#[cfg(target_os = "ios")]
{
// 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,
// `msg_send![view, window]` and `msg_send![window, screen]` will get null.
let screen: *mut Object = msg_send![class!(UIScreen), mainScreen];
Expand All @@ -113,9 +131,9 @@ impl super::Surface {
};
#[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![new_layer.as_ref(), setContentsGravity: kCAGravityTopLeft];
let () = msg_send![new_layer, setContentsGravity: kCAGravityTopLeft];
let window: *mut Object = msg_send![view, window];
if !window.is_null() {
let scale_factor: CGFloat = msg_send![window, backingScaleFactor];
Expand All @@ -126,17 +144,7 @@ impl super::Surface {
let () = msg_send![new_layer, setDelegate: delegate.0];
}
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 {
Expand Down
40 changes: 1 addition & 39 deletions wgpu-hal/src/vulkan/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,46 +415,8 @@ impl super::Instance {

#[cfg(any(target_os = "macos", target_os = "ios"))]
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 view = view as *mut Object;
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
}
crate::metal::Surface::get_metal_layer(view as *mut objc::runtime::Object, None)
};

let surface = {
Expand Down