From ba3b823e1c6a1bb744c8deb3a0e31dbb119b2170 Mon Sep 17 00:00:00 2001 From: Ryan Hileman Date: Sun, 24 Apr 2022 07:31:19 -0700 Subject: [PATCH] use CALayer for macOS backend --- Cargo.toml | 4 +++- src/cg.rs | 50 ++++++++++++++++++++++---------------------------- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8022e3b..b2f9b8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,9 @@ x11-dl = "2.19.1" winapi = "0.3.9" [target.'cfg(target_os = "macos")'.dependencies] +cocoa = "0.24.0" core-graphics = "0.22.3" +foreign-types = "0.3.0" objc = "0.2.7" [target.'cfg(target_arch = "wasm32")'.dependencies] @@ -49,4 +51,4 @@ features = ["jpeg"] [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] # Turn rayon back on everywhere else; creating the separate entry resets the features to default. image = "0.23.14" -rayon = "1.5.1" \ No newline at end of file +rayon = "1.5.1" diff --git a/src/cg.rs b/src/cg.rs index 7574e33..a8fecc6 100644 --- a/src/cg.rs +++ b/src/cg.rs @@ -1,42 +1,30 @@ use crate::{GraphicsContextImpl, SoftBufferError}; use raw_window_handle::{HasRawWindowHandle, AppKitHandle}; -use objc::runtime::Object; use core_graphics::base::{kCGBitmapByteOrder32Little, kCGImageAlphaNoneSkipFirst, kCGRenderingIntentDefault}; use core_graphics::color_space::CGColorSpace; -use core_graphics::context::CGContext; use core_graphics::data_provider::CGDataProvider; -use core_graphics::geometry::{CGPoint, CGSize, CGRect}; +use core_graphics::geometry::CGSize; use core_graphics::image::CGImage; -use core_graphics::sys; + +use cocoa::base::id; +use cocoa::quartzcore::CALayer; +use foreign_types::ForeignType; pub struct CGImpl { - view: *mut Object, + layer: CALayer, } impl CGImpl { pub unsafe fn new(handle: AppKitHandle) -> Result> { - let window = handle.ns_window as *mut Object; - let view = handle.ns_view as *mut Object; - let cls = class!(NSGraphicsContext); - let graphics_context: *mut Object = msg_send![cls, graphicsContextWithWindow:window]; - if graphics_context.is_null() { - return Err(SoftBufferError::PlatformError(Some("Graphics context is null".into()), None)); - } - let _: () = msg_send![cls, setCurrentContext:graphics_context]; - Ok( - Self { - view, - } - ) + let view = handle.ns_view as id; + let layer = CALayer::new(); + let _: () = msg_send![view, setLayer:layer.clone()]; + Ok(Self{layer}) } } impl GraphicsContextImpl for CGImpl { unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) { - let cls = class!(NSGraphicsContext); - let graphics_context: *mut Object = msg_send![cls, currentContext]; - let context_ptr: *mut sys::CGContext = msg_send![graphics_context, CGContext]; - let context = CGContext::from_existing_context_ptr(context_ptr); let color_space = CGColorSpace::create_device_rgb(); let slice = std::slice::from_raw_parts( buffer.as_ptr() as *const u8, @@ -54,11 +42,17 @@ impl GraphicsContextImpl for CGImpl { false, kCGRenderingIntentDefault, ); - let frame: CGRect = msg_send![self.view, frame]; - // In Core Graphics, (0, 0) is bottom left, not top left - let origin = CGPoint { x: 0f64, y: frame.size.height }; - let size = CGSize { width: width as f64, height: -(height as f64) }; - let rect = CGRect { origin, size }; - context.draw_image(rect, &image); + + let size = CGSize::new(width as f64, height as f64); + let rep: id = msg_send![class!(NSCGImageRep), alloc]; + let rep: id = msg_send![rep, initWithCGImage:image.as_ptr() size:size]; + + let nsimage: id = msg_send![class!(NSImage), alloc]; + let nsimage: id = msg_send![nsimage, initWithSize:size]; + let _: () = msg_send![nsimage, addRepresentation:rep]; + let _: () = msg_send![rep, release]; + + self.layer.set_contents(nsimage); + let _: () = msg_send![nsimage, release]; } }