11// Copyright © SixtyFPS GmbH <info@slint.dev>
22// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
33
4- use cocoa:: { appkit:: NSView , base:: id as cocoa_id} ;
54use core_graphics_types:: geometry:: CGSize ;
6- use foreign_types:: ForeignTypeRef ;
5+ use foreign_types:: { ForeignType , ForeignTypeRef } ;
76use i_slint_core:: api:: PhysicalSize as PhysicalWindowSize ;
87use metal:: MTLPixelFormat ;
9- use objc:: { rc:: autoreleasepool, runtime:: YES } ;
8+ use objc:: { msg_send, sel, sel_impl} ;
9+ use objc:: {
10+ rc:: autoreleasepool,
11+ runtime:: { Object , BOOL , NO } ,
12+ } ;
1013
1114use skia_safe:: gpu:: mtl;
1215
1316use std:: cell:: RefCell ;
1417use std:: rc:: Rc ;
1518
19+ #[ link( name = "QuartzCore" , kind = "framework" ) ]
20+ extern "C" {
21+ #[ allow( non_upper_case_globals) ]
22+ static kCAGravityTopLeft: * mut Object ;
23+ #[ allow( non_upper_case_globals) ]
24+ static kCAGravityBottomLeft: * mut Object ;
25+ }
26+
1627/// This surface renders into the given window using Metal. The provided display argument
1728/// is ignored, as it has no meaning on macOS.
1829pub struct MetalSurface {
@@ -27,36 +38,40 @@ impl super::Surface for MetalSurface {
2738 _display_handle : Rc < dyn raw_window_handle:: HasDisplayHandle > ,
2839 size : PhysicalWindowSize ,
2940 ) -> Result < Self , i_slint_core:: platform:: PlatformError > {
41+ let layer = match window_handle
42+ . window_handle ( )
43+ . map_err ( |e| format ! ( "Error obtaining window handle for skia metal renderer: {e}" ) ) ?
44+ . as_raw ( )
45+ {
46+ raw_window_handle:: RawWindowHandle :: AppKit ( handle) => unsafe {
47+ raw_window_metal:: Layer :: from_ns_view ( handle. ns_view )
48+ } ,
49+ raw_window_handle:: RawWindowHandle :: UiKit ( handle) => unsafe {
50+ raw_window_metal:: Layer :: from_ui_view ( handle. ui_view )
51+ } ,
52+ _ => return Err ( "Skia Renderer: Metal surface is only supported with AppKit" . into ( ) ) ,
53+ } ;
54+
55+ // SAFETY: The layer is an initialized instance of `CAMetalLayer`, and
56+ // we transfer the retain count to `MetalLayer` using `into_raw`.
57+ let layer = unsafe { metal:: MetalLayer :: from_ptr ( layer. into_raw ( ) . cast ( ) . as_ptr ( ) ) } ;
58+
3059 let device = metal:: Device :: system_default ( )
3160 . ok_or_else ( || format ! ( "Skia Renderer: No metal device found" ) ) ?;
32-
33- let layer = metal:: MetalLayer :: new ( ) ;
3461 layer. set_device ( & device) ;
3562 layer. set_pixel_format ( MTLPixelFormat :: BGRA8Unorm ) ;
3663 layer. set_opaque ( false ) ;
3764 layer. set_presents_with_transaction ( false ) ;
3865
3966 layer. set_drawable_size ( CGSize :: new ( size. width as f64 , size. height as f64 ) ) ;
4067
41- unsafe {
42- let view = match window_handle
43- . window_handle ( )
44- . map_err ( |e| format ! ( "Error obtaining window handle for skia metal renderer: {e}" ) ) ?
45- . as_raw ( )
46- {
47- raw_window_handle:: RawWindowHandle :: AppKit (
48- raw_window_handle:: AppKitWindowHandle { ns_view, .. } ,
49- ) => ns_view. as_ptr ( ) ,
50- _ => {
51- return Err ( "Skia Renderer: Metal surface is only supported with AppKit" . into ( ) )
52- }
53- } as cocoa_id ;
54- view. setWantsLayer ( YES ) ;
55- view. setLayer ( layer. as_ref ( ) as * const _ as _ ) ;
56- view. setLayerContentsPlacement (
57- cocoa:: appkit:: NSViewLayerContentsPlacement :: NSViewLayerContentsPlacementTopLeft ,
58- ) ;
59- }
68+ let flipped: BOOL = unsafe { msg_send ! [ layer. as_ptr( ) , contentsAreFlipped] } ;
69+ let gravity = if flipped == NO {
70+ unsafe { kCAGravityTopLeft }
71+ } else {
72+ unsafe { kCAGravityBottomLeft }
73+ } ;
74+ let _: ( ) = unsafe { msg_send ! [ layer. as_ptr( ) , setContentsGravity: gravity] } ;
6075
6176 let command_queue = device. new_command_queue ( ) ;
6277
@@ -85,10 +100,6 @@ impl super::Surface for MetalSurface {
85100 Ok ( ( ) )
86101 }
87102
88- fn set_scale_factor ( & self , scale_factor : f32 ) {
89- self . layer . set_contents_scale ( scale_factor. into ( ) ) ;
90- }
91-
92103 fn render (
93104 & self ,
94105 _size : PhysicalWindowSize ,
0 commit comments