hal/metal: inherit scaling from NSView

This commit is contained in:
Dzmitry Malyshau 2021-08-27 12:49:48 -04:00 committed by Dzmitry Malyshau
parent 9c0b519373
commit 50f5deed6c
2 changed files with 55 additions and 10 deletions

View File

@ -61,7 +61,9 @@ impl crate::Api for Api {
type ComputePipeline = ComputePipeline;
}
pub struct Instance {}
pub struct Instance {
managed_metal_layer_delegate: surface::HalManagedMetalLayerDelegate,
}
impl Instance {
pub fn create_surface_from_layer(&self, layer: &mtl::MetalLayerRef) -> Surface {
@ -72,7 +74,9 @@ impl Instance {
impl crate::Instance<Api> for Instance {
unsafe fn init(_desc: &crate::InstanceDescriptor) -> Result<Self, crate::InstanceError> {
//TODO: enable `METAL_DEVICE_WRAPPER_TYPE` environment based on the flags?
Ok(Instance {})
Ok(Instance {
managed_metal_layer_delegate: surface::HalManagedMetalLayerDelegate::new(),
})
}
unsafe fn create_surface(
@ -82,12 +86,14 @@ impl crate::Instance<Api> for Instance {
match has_handle.raw_window_handle() {
#[cfg(target_os = "ios")]
raw_window_handle::RawWindowHandle::IOS(handle) => {
let _ = &self.managed_metal_layer_delegate;
Ok(Surface::from_uiview(handle.ui_view))
}
#[cfg(target_os = "macos")]
raw_window_handle::RawWindowHandle::MacOS(handle) => {
Ok(Surface::from_nsview(handle.ns_view))
}
raw_window_handle::RawWindowHandle::MacOS(handle) => Ok(Surface::from_nsview(
handle.ns_view,
&self.managed_metal_layer_delegate,
)),
_ => Err(crate::InstanceError),
}
}

View File

@ -1,13 +1,15 @@
use std::{mem, os::raw::c_void, ptr::NonNull, thread};
use std::{mem, os::raw::c_void, ptr::NonNull, sync::Once, thread};
use core_graphics_types::{
base::CGFloat,
geometry::{CGRect, CGSize},
};
use objc::{
class, msg_send,
class,
declare::ClassDecl,
msg_send,
rc::autoreleasepool,
runtime::{Object, BOOL, YES},
runtime::{Class, Object, Sel, BOOL, YES},
sel, sel_impl,
};
use parking_lot::Mutex;
@ -19,6 +21,40 @@ extern "C" {
static kCAGravityTopLeft: *mut Object;
}
extern "C" fn layer_should_inherit_contents_scale_from_window(
_: &Class,
_: Sel,
_layer: *mut Object,
_new_scale: CGFloat,
_from_window: *mut Object,
) -> BOOL {
YES
}
const CAML_DELEGATE_CLASS: &str = "HalManagedMetalLayerDelegate";
static CAML_DELEGATE_REGISTER: Once = Once::new();
#[derive(Debug)]
pub struct HalManagedMetalLayerDelegate(&'static Class);
impl HalManagedMetalLayerDelegate {
pub fn new() -> Self {
CAML_DELEGATE_REGISTER.call_once(|| {
type Fun = extern "C" fn(&Class, Sel, *mut Object, CGFloat, *mut Object) -> BOOL;
let mut decl = ClassDecl::new(CAML_DELEGATE_CLASS, class!(NSObject)).unwrap();
#[allow(trivial_casts)] // false positive
unsafe {
decl.add_class_method(
sel!(layer:shouldInheritContentsScale:fromWindow:),
layer_should_inherit_contents_scale_from_window as Fun,
);
}
decl.register();
});
Self(Class::get(CAML_DELEGATE_CLASS).unwrap())
}
}
impl super::Surface {
fn new(view: Option<NonNull<Object>>, layer: mtl::MetalLayer) -> Self {
Self {
@ -74,7 +110,10 @@ impl super::Surface {
#[cfg(target_os = "macos")]
#[allow(clippy::transmute_ptr_to_ref)]
pub unsafe fn from_nsview(nsview: *mut c_void) -> Self {
pub unsafe fn from_nsview(
nsview: *mut c_void,
delegate: &HalManagedMetalLayerDelegate,
) -> Self {
let view = nsview as *mut Object;
if view.is_null() {
panic!("window does not have a valid contentView");
@ -109,7 +148,7 @@ impl super::Surface {
let scale_factor: CGFloat = msg_send![window, backingScaleFactor];
let () = msg_send![layer, setContentsScale: scale_factor];
}
//let () = msg_send![layer, setDelegate: self.gfx_managed_metal_layer_delegate.0];
let () = msg_send![layer, setDelegate: delegate.0];
layer
};