Skip to content

Commit 1bf19cf

Browse files
authored
Fix deprecations in objc2-core-foundation v0.3.1 (#264)
* Fix CI MSRV * Fix deprecations in objc2-core-foundation v0.3.1 * Improve CG thread-safety documentation a bit CGColorSpace is marked Send+Sync in objc2-core-graphics, and CALayer won't be, for the reasons described in the comments.
1 parent ba60228 commit 1bf19cf

File tree

3 files changed

+25
-29
lines changed

3 files changed

+25
-29
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ jobs:
9898
- name: Pin deps that break MSRV
9999
if: matrix.rust_version == '1.71.0'
100100
run: |
101+
cargo update -p half --precise 2.4.1
101102
cargo update -p bumpalo --precise 3.14.0
102103
103104
- name: Build crate

Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,19 +81,19 @@ features = [
8181
]
8282

8383
[target.'cfg(target_vendor = "apple")'.dependencies]
84-
objc2-core-graphics = { version = "0.3.0", default-features = false, features = [
84+
objc2-core-graphics = { version = "0.3.1", default-features = false, features = [
8585
"std",
8686
"objc2",
8787
"CGColorSpace",
8888
"CGDataProvider",
8989
"CGImage",
9090
] }
9191
objc2 = "0.6.0"
92-
objc2-core-foundation = { version = "0.3.0", default-features = false, features = [
92+
objc2-core-foundation = { version = "0.3.1", default-features = false, features = [
9393
"std",
9494
"CFCGTypes",
9595
] }
96-
objc2-foundation = { version = "0.3.0", default-features = false, features = [
96+
objc2-foundation = { version = "0.3.1", default-features = false, features = [
9797
"std",
9898
"objc2-core-foundation",
9999
"NSDictionary",
@@ -103,7 +103,7 @@ objc2-foundation = { version = "0.3.0", default-features = false, features = [
103103
"NSThread",
104104
"NSValue",
105105
] }
106-
objc2-quartz-core = { version = "0.3.0", default-features = false, features = [
106+
objc2-quartz-core = { version = "0.3.1", default-features = false, features = [
107107
"std",
108108
"objc2-core-foundation",
109109
"CALayer",

src/backends/cg.rs

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//! Softbuffer implementation using CoreGraphics.
12
use crate::backend_interface::*;
23
use crate::error::InitError;
34
use crate::{Rect, SoftBufferError};
@@ -6,8 +7,7 @@ use objc2::runtime::{AnyObject, Bool};
67
use objc2::{define_class, msg_send, AllocAnyThread, DefinedClass, MainThreadMarker, Message};
78
use objc2_core_foundation::{CFRetained, CGPoint};
89
use objc2_core_graphics::{
9-
CGBitmapInfo, CGColorRenderingIntent, CGColorSpace, CGColorSpaceCreateDeviceRGB,
10-
CGDataProviderCreateWithData, CGImageAlphaInfo, CGImageCreate,
10+
CGBitmapInfo, CGColorRenderingIntent, CGColorSpace, CGDataProvider, CGImage, CGImageAlphaInfo,
1111
};
1212
use objc2_foundation::{
1313
ns_string, NSDictionary, NSKeyValueChangeKey, NSKeyValueChangeNewKey,
@@ -27,7 +27,7 @@ use std::ptr::{self, slice_from_raw_parts_mut, NonNull};
2727
define_class!(
2828
#[unsafe(super(NSObject))]
2929
#[name = "SoftbufferObserver"]
30-
#[ivars = Retained<CALayer>]
30+
#[ivars = SendCALayer]
3131
struct Observer;
3232

3333
/// NSKeyValueObserving
@@ -45,13 +45,9 @@ define_class!(
4545
}
4646
);
4747

48-
// SAFETY: The `CALayer` that the observer contains is thread safe.
49-
unsafe impl Send for Observer {}
50-
unsafe impl Sync for Observer {}
51-
5248
impl Observer {
5349
fn new(layer: &CALayer) -> Retained<Self> {
54-
let this = Self::alloc().set_ivars(layer.retain());
50+
let this = Self::alloc().set_ivars(SendCALayer(layer.retain()));
5551
unsafe { msg_send![super(this), init] }
5652
}
5753

@@ -64,11 +60,9 @@ impl Observer {
6460

6561
let change =
6662
change.expect("requested a change dictionary in `addObserver`, but none was provided");
67-
let new = unsafe {
68-
change
69-
.objectForKey(NSKeyValueChangeNewKey)
70-
.expect("requested change dictionary did not contain `NSKeyValueChangeNewKey`")
71-
};
63+
let new = change
64+
.objectForKey(unsafe { NSKeyValueChangeNewKey })
65+
.expect("requested change dictionary did not contain `NSKeyValueChangeNewKey`");
7266

7367
// NOTE: Setting these values usually causes a quarter second animation to occur, which is
7468
// undesirable.
@@ -106,7 +100,7 @@ pub struct CGImpl<D, W> {
106100
/// Can also be retrieved from `layer.superlayer()`.
107101
root_layer: SendCALayer,
108102
observer: Retained<Observer>,
109-
color_space: SendCGColorSpace,
103+
color_space: CFRetained<CGColorSpace>,
110104
/// The width of the underlying buffer.
111105
width: usize,
112106
/// The height of the underlying buffer.
@@ -229,7 +223,7 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for CGImpl<
229223
layer.setContentsGravity(unsafe { kCAGravityTopLeft });
230224

231225
// Initialize color space here, to reduce work later on.
232-
let color_space = unsafe { CGColorSpaceCreateDeviceRGB() }.unwrap();
226+
let color_space = unsafe { CGColorSpace::new_device_rgb() }.unwrap();
233227

234228
// Grab initial width and height from the layer (whose properties have just been initialized
235229
// by the observer using `NSKeyValueObservingOptionInitial`).
@@ -242,7 +236,7 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for CGImpl<
242236
layer: SendCALayer(layer),
243237
root_layer: SendCALayer(root_layer),
244238
observer,
245-
color_space: SendCGColorSpace(color_space),
239+
color_space,
246240
width,
247241
height,
248242
_display: PhantomData,
@@ -310,18 +304,18 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> BufferInterface for BufferImpl<'_,
310304
// SAFETY: The data pointer and length are valid.
311305
// The info pointer can safely be NULL, we don't use it in the `release` callback.
312306
unsafe {
313-
CGDataProviderCreateWithData(ptr::null_mut(), data_ptr, len, Some(release)).unwrap()
307+
CGDataProvider::with_data(ptr::null_mut(), data_ptr, len, Some(release)).unwrap()
314308
}
315309
};
316310

317311
let image = unsafe {
318-
CGImageCreate(
312+
CGImage::new(
319313
self.imp.width,
320314
self.imp.height,
321315
8,
322316
32,
323317
self.imp.width * 4,
324-
Some(&self.imp.color_space.0),
318+
Some(&self.imp.color_space),
325319
// TODO: This looks incorrect!
326320
CGBitmapInfo::ByteOrder32Little | CGBitmapInfo(CGImageAlphaInfo::NoneSkipFirst.0),
327321
Some(&data_provider),
@@ -350,16 +344,17 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> BufferInterface for BufferImpl<'_,
350344
}
351345
}
352346

353-
struct SendCGColorSpace(CFRetained<CGColorSpace>);
354-
// SAFETY: `CGColorSpace` is immutable, and can freely be shared between threads.
355-
unsafe impl Send for SendCGColorSpace {}
356-
unsafe impl Sync for SendCGColorSpace {}
357-
358347
struct SendCALayer(Retained<CALayer>);
359-
// CALayer is thread safe, like most things in Core Animation, see:
348+
349+
// SAFETY: CALayer is dubiously thread safe, like most things in Core Animation.
350+
// But since we make sure to do our changes within a CATransaction, it is
351+
// _probably_ fine for us to use CALayer from different threads.
352+
//
353+
// See also:
360354
// https://developer.apple.com/documentation/quartzcore/catransaction/1448267-lock?language=objc
361355
// https://stackoverflow.com/questions/76250226/how-to-render-content-of-calayer-on-a-background-thread
362356
unsafe impl Send for SendCALayer {}
357+
// SAFETY: Same as above.
363358
unsafe impl Sync for SendCALayer {}
364359

365360
impl Deref for SendCALayer {

0 commit comments

Comments
 (0)