Skip to content

Commit a085537

Browse files
authored
Use objc2-* family of crates (#334)
* Use objc2 * Avoid premature Retained::retain * Use expect instead of unwrap on missing NSWindow
1 parent 0c1861e commit a085537

File tree

9 files changed

+396
-277
lines changed

9 files changed

+396
-277
lines changed

Cargo.toml

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,62 @@ serial_test = "3.1.0"
5656

5757
[target.'cfg(target_os = "macos")'.dependencies]
5858
cgl = "0.3.2"
59-
cocoa = "0.25"
60-
core-foundation = "0.9"
61-
core-graphics = "0.23"
62-
servo-display-link = "0.2"
63-
io-surface = "0.15"
6459
mach2 = "0.4"
65-
metal = "0.24"
66-
objc = "0.2"
60+
objc2 = "0.6.1"
61+
objc2-app-kit = { version = "0.3", default-features = false, features = [
62+
"std",
63+
"objc2-quartz-core",
64+
"objc2-core-foundation",
65+
"NSResponder",
66+
"NSScreen",
67+
"NSView",
68+
"NSGraphics",
69+
"NSWindow",
70+
] }
71+
objc2-core-foundation = { version = "0.3.1", default-features = false, features = [
72+
"std",
73+
"CFBase",
74+
"CFBundle",
75+
"CFCGTypes",
76+
"CFDictionary",
77+
"CFNumber",
78+
"CFString",
79+
] }
80+
objc2-core-video = { version = "0.3.1", default-features = false, features = [
81+
"std",
82+
"objc2-core-graphics",
83+
"CVBase",
84+
"CVDisplayLink",
85+
"CVPixelBuffer",
86+
"CVReturn",
87+
] }
88+
objc2-foundation = { version = "0.3.1", default-features = false, features = [
89+
"std",
90+
"objc2-core-foundation",
91+
"NSEnumerator",
92+
"NSGeometry",
93+
"NSString",
94+
"NSValue",
95+
] }
96+
objc2-io-surface = { version = "0.3.1", default-features = false, features = [
97+
"std",
98+
"libc",
99+
"objc2",
100+
"objc2-core-foundation",
101+
"IOSurfaceRef",
102+
"IOSurfaceTypes",
103+
] }
104+
objc2-metal = { version = "0.3.1", default-features = false, features = [
105+
"std",
106+
"MTLDevice",
107+
] }
108+
objc2-quartz-core = { version = "0.3.1", default-features = false, features = [
109+
"std",
110+
"objc2-core-foundation",
111+
"CALayer",
112+
"CATransaction",
113+
"CATransform3D",
114+
] }
67115

68116
[target.'cfg(all(unix, not(any(target_os = "macos", target_os = "android", target_env = "ohos"))))'.dependencies.wayland-sys]
69117
version = "0.30"

src/lib.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@ extern crate bitflags;
1616
#[macro_use]
1717
extern crate log;
1818

19-
#[cfg(target_os = "macos")]
20-
#[macro_use]
21-
extern crate objc;
22-
2319
pub mod platform;
2420
pub use platform::default::connection::{Connection, NativeConnection};
2521
pub use platform::default::context::{Context, ContextDescriptor, NativeContext};

src/platform/macos/cgl/connection.rs

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,26 @@ impl Connection {
125125
raw_handle: rwh_05::RawWindowHandle,
126126
_size: Size2D<i32>,
127127
) -> Result<NativeWidget, Error> {
128-
use crate::platform::macos::system::surface::NSView;
129-
use cocoa::base::id;
128+
use objc2::{MainThreadMarker, Message};
129+
use objc2_app_kit::{NSView, NSWindow};
130130
use rwh_05::RawWindowHandle::AppKit;
131131

132132
match raw_handle {
133-
AppKit(handle) => Ok(NativeWidget {
134-
view: NSView(unsafe { msg_send![handle.ns_view as id, retain] }),
135-
opaque: unsafe { msg_send![handle.ns_window as id, isOpaque] },
136-
}),
133+
AppKit(handle) => {
134+
assert!(
135+
MainThreadMarker::new().is_some(),
136+
"NSView is only usable on the main thread"
137+
);
138+
// SAFETY: The pointer is valid for as long as the handle is,
139+
// and we just checked that we're on the main thread.
140+
let ns_view = unsafe { handle.ns_view.cast::<NSView>().as_ref().unwrap() };
141+
let ns_window = unsafe { handle.ns_window.cast::<NSWindow>().as_ref().unwrap() };
142+
143+
Ok(NativeWidget {
144+
view: ns_view.retain(),
145+
opaque: unsafe { ns_window.isOpaque() },
146+
})
147+
}
137148
_ => Err(Error::IncompatibleNativeWidget),
138149
}
139150
}
@@ -146,21 +157,26 @@ impl Connection {
146157
handle: rwh_06::WindowHandle,
147158
_size: Size2D<i32>,
148159
) -> Result<NativeWidget, Error> {
149-
use crate::platform::macos::system::surface::NSView;
150-
use cocoa::base::id;
160+
use objc2::{MainThreadMarker, Message};
161+
use objc2_app_kit::NSView;
151162
use rwh_06::RawWindowHandle::AppKit;
152163

153164
match handle.as_raw() {
154165
AppKit(handle) => {
155-
let ns_view = handle.ns_view.as_ptr() as id;
156-
// https://developer.apple.com/documentation/appkit/nsview/1483301-window
157-
let ns_window: id = unsafe { msg_send![ns_view, window] };
166+
assert!(
167+
MainThreadMarker::new().is_some(),
168+
"NSView is only usable on the main thread"
169+
);
170+
// SAFETY: The pointer is valid for as long as the handle is,
171+
// and we just checked that we're on the main thread.
172+
let ns_view = unsafe { handle.ns_view.cast::<NSView>().as_ref() };
173+
let ns_window = ns_view
174+
.window()
175+
.expect("view must be installed in a window");
158176
Ok(NativeWidget {
159-
// Increment the nsview's reference count with retain. See:
160-
// https://developer.apple.com/documentation/objectivec/1418956-nsobject/1571946-retain
161-
view: NSView(unsafe { msg_send![ns_view, retain] }),
162-
// https://developer.apple.com/documentation/appkit/nswindow/1419086-isopaque
163-
opaque: unsafe { msg_send![ns_window, isOpaque] },
177+
// Extend the lifetime of the view.
178+
view: ns_view.retain(),
179+
opaque: unsafe { ns_window.isOpaque() },
164180
})
165181
}
166182
_ => Err(Error::IncompatibleNativeWidget),

src/platform/macos/cgl/context.rs

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,12 @@ use cgl::{
1818
};
1919
use cgl::{CGLGetCurrentContext, CGLGetPixelFormat, CGLPixelFormatAttribute, CGLPixelFormatObj};
2020
use cgl::{CGLReleasePixelFormat, CGLRetainPixelFormat, CGLSetCurrentContext};
21-
use core_foundation::base::TCFType;
22-
use core_foundation::bundle::CFBundleGetBundleWithIdentifier;
23-
use core_foundation::bundle::CFBundleGetFunctionPointerForName;
24-
use core_foundation::bundle::CFBundleRef;
25-
use core_foundation::string::CFString;
2621
use glow::HasContext;
22+
use objc2_core_foundation::{CFBundle, CFRetained, CFString};
2723
use std::mem;
2824
use std::os::raw::c_void;
2925
use std::ptr;
3026
use std::rc::Rc;
31-
use std::str::FromStr;
3227
use std::thread;
3328

3429
// No CGL error occurred.
@@ -48,15 +43,10 @@ const kCGLOGLPVersion_GL4_Core: CGLPixelFormatAttribute = 0x4100;
4843
static OPENGL_FRAMEWORK_IDENTIFIER: &str = "com.apple.opengl";
4944

5045
thread_local! {
51-
static OPENGL_FRAMEWORK: CFBundleRef = {
52-
unsafe {
53-
let framework_identifier: CFString =
54-
FromStr::from_str(OPENGL_FRAMEWORK_IDENTIFIER).unwrap();
55-
let framework =
56-
CFBundleGetBundleWithIdentifier(framework_identifier.as_concrete_TypeRef());
57-
assert!(!framework.is_null());
58-
framework
59-
}
46+
static OPENGL_FRAMEWORK: CFRetained<CFBundle> = {
47+
let framework_identifier = CFString::from_str(OPENGL_FRAMEWORK_IDENTIFIER);
48+
let framework = CFBundle::bundle_with_identifier(Some(&framework_identifier));
49+
framework.unwrap()
6050
};
6151
}
6252

@@ -495,9 +485,9 @@ impl Device {
495485
}
496486

497487
fn get_proc_address(symbol_name: &str) -> *const c_void {
498-
OPENGL_FRAMEWORK.with(|framework| unsafe {
499-
let symbol_name: CFString = FromStr::from_str(symbol_name).unwrap();
500-
CFBundleGetFunctionPointerForName(*framework, symbol_name.as_concrete_TypeRef())
488+
OPENGL_FRAMEWORK.with(|framework| {
489+
let symbol_name = CFString::from_str(symbol_name);
490+
framework.function_pointer_for_name(Some(&symbol_name))
501491
})
502492
}
503493

src/platform/macos/cgl/surface.rs

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ use crate::gl_utils;
99
use crate::platform::macos::system::surface::Surface as SystemSurface;
1010
use crate::renderbuffers::Renderbuffers;
1111
use crate::{gl, Error, SurfaceAccess, SurfaceID, SurfaceInfo, SurfaceType, WindowingApiError};
12+
use cgl::{kCGLNoError, CGLErrorString, CGLGetCurrentContext, CGLTexImageIOSurface2D, GLenum};
1213
use glow::Context as Gl;
1314

14-
use core_foundation::base::TCFType;
1515
use euclid::default::Size2D;
1616
use glow::{HasContext, Texture};
17-
use io_surface::{self, IOSurface};
17+
use objc2_io_surface::IOSurfaceRef;
18+
use std::ffi::CStr;
1819
use std::fmt::{self, Debug, Formatter};
1920
use std::marker::PhantomData;
2021
use std::rc::Rc;
@@ -76,6 +77,38 @@ impl Debug for SurfaceTexture {
7677
}
7778
}
7879

80+
fn surface_bind_to_gl_texture(surface: &IOSurfaceRef, width: i32, height: i32, has_alpha: bool) {
81+
const BGRA: GLenum = 0x80E1;
82+
const RGBA: GLenum = 0x1908;
83+
const RGB: GLenum = 0x1907;
84+
const TEXTURE_RECTANGLE_ARB: GLenum = 0x84F5;
85+
const UNSIGNED_INT_8_8_8_8_REV: GLenum = 0x8367;
86+
87+
unsafe {
88+
let context = CGLGetCurrentContext();
89+
let gl_error = CGLTexImageIOSurface2D(
90+
context,
91+
TEXTURE_RECTANGLE_ARB,
92+
if has_alpha {
93+
RGBA as GLenum
94+
} else {
95+
RGB as GLenum
96+
},
97+
width,
98+
height,
99+
BGRA as GLenum,
100+
UNSIGNED_INT_8_8_8_8_REV,
101+
surface as *const IOSurfaceRef as cgl::IOSurfaceRef,
102+
0,
103+
);
104+
105+
if gl_error != kCGLNoError {
106+
let error_msg = CStr::from_ptr(CGLErrorString(gl_error));
107+
panic!("{}", error_msg.to_string_lossy());
108+
}
109+
}
110+
}
111+
79112
impl Device {
80113
/// Creates either a generic or a widget surface, depending on the supplied surface type.
81114
///
@@ -172,12 +205,17 @@ impl Device {
172205
})
173206
}
174207

175-
fn bind_to_gl_texture(&self, gl: &Gl, io_surface: &IOSurface, size: &Size2D<i32>) -> Texture {
208+
fn bind_to_gl_texture(
209+
&self,
210+
gl: &Gl,
211+
io_surface: &IOSurfaceRef,
212+
size: &Size2D<i32>,
213+
) -> Texture {
176214
unsafe {
177215
let texture = gl.create_texture().unwrap();
178216

179217
gl.bind_texture(gl::TEXTURE_RECTANGLE, Some(texture));
180-
io_surface.bind_to_gl_texture(size.width, size.height, true);
218+
surface_bind_to_gl_texture(io_surface, size.width, size.height, true);
181219

182220
gl.tex_parameter_i32(
183221
gl::TEXTURE_RECTANGLE,
@@ -291,10 +329,12 @@ impl Device {
291329
unsafe {
292330
let size = surface.system_surface.size;
293331
gl.bind_texture(gl::TEXTURE_RECTANGLE, surface.texture_object);
294-
surface
295-
.system_surface
296-
.io_surface
297-
.bind_to_gl_texture(size.width, size.height, true);
332+
surface_bind_to_gl_texture(
333+
&surface.system_surface.io_surface,
334+
size.width,
335+
size.height,
336+
true,
337+
);
298338
gl.bind_texture(gl::TEXTURE_RECTANGLE, None);
299339
}
300340

@@ -403,7 +443,7 @@ impl Device {
403443
impl Surface {
404444
#[inline]
405445
fn id(&self) -> SurfaceID {
406-
SurfaceID(self.system_surface.io_surface.as_concrete_TypeRef() as usize)
446+
SurfaceID(&*self.system_surface.io_surface as *const IOSurfaceRef as usize)
407447
}
408448
}
409449

0 commit comments

Comments
 (0)