diff --git a/CHANGELOG.md b/CHANGELOG.md index c93804e..20c27ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Unreleased +- Improved performance when presenting on macOS. - Update to `objc2` 0.6.0. - Bump MSRV to Rust 1.71. - Make `Context` cloneable. diff --git a/Cargo.toml b/Cargo.toml index d866e24..f5f2806 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -102,6 +102,7 @@ objc2-foundation = { version = "0.3.1", default-features = false, features = [ "NSString", "NSThread", "NSValue", + "NSNull", ] } objc2-quartz-core = { version = "0.3.1", default-features = false, features = [ "std", diff --git a/src/backends/cg.rs b/src/backends/cg.rs index ba6c17a..8240283 100644 --- a/src/backends/cg.rs +++ b/src/backends/cg.rs @@ -3,7 +3,7 @@ use crate::backend_interface::*; use crate::error::InitError; use crate::{Rect, SoftBufferError}; use objc2::rc::Retained; -use objc2::runtime::{AnyObject, Bool}; +use objc2::runtime::{AnyObject, Bool, ProtocolObject}; use objc2::{define_class, msg_send, AllocAnyThread, DefinedClass, MainThreadMarker, Message}; use objc2_core_foundation::{CFRetained, CGPoint}; use objc2_core_graphics::{ @@ -11,10 +11,10 @@ use objc2_core_graphics::{ }; use objc2_foundation::{ ns_string, NSDictionary, NSKeyValueChangeKey, NSKeyValueChangeNewKey, - NSKeyValueObservingOptions, NSNumber, NSObject, NSObjectNSKeyValueObserverRegistration, + NSKeyValueObservingOptions, NSNull, NSNumber, NSObject, NSObjectNSKeyValueObserverRegistration, NSString, NSValue, }; -use objc2_quartz_core::{kCAGravityTopLeft, CALayer, CATransaction}; +use objc2_quartz_core::{kCAGravityTopLeft, CALayer}; use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawWindowHandle}; use std::ffi::c_void; @@ -222,6 +222,17 @@ impl SurfaceInterface for CGImpl< // resized to something that doesn't fit, see #177. layer.setContentsGravity(unsafe { kCAGravityTopLeft }); + // The CALayer has a default action associated with a change in the layer contents, causing + // a quarter second fade transition to happen every time a new buffer is applied. + // + // We avoid this by setting the action for the "contents" key to NULL. + // + // TODO(madsmtm): Do we want to do the same for bounds/contentsScale for smoother resizing? + layer.setActions(Some(&NSDictionary::from_slices( + &[ns_string!("contents")], + &[ProtocolObject::from_ref(&*unsafe { NSNull::null() })], + ))); + // Initialize color space here, to reduce work later on. let color_space = unsafe { CGColorSpace::new_device_rgb() }.unwrap(); @@ -326,16 +337,9 @@ impl BufferInterface for BufferImpl<'_, } .unwrap(); - // The CALayer has a default action associated with a change in the layer contents, causing - // a quarter second fade transition to happen every time a new buffer is applied. This can - // be avoided by wrapping the operation in a transaction and disabling all actions. - CATransaction::begin(); - CATransaction::setDisableActions(true); - // SAFETY: The contents is `CGImage`, which is a valid class for `contents`. unsafe { self.imp.layer.setContents(Some(image.as_ref())) }; - CATransaction::commit(); Ok(()) }