From 3d18b97c4273661252d19fdb8f0be62e2f8f3703 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Tue, 1 Aug 2023 00:39:31 +0200 Subject: [PATCH] Update objc2 to v0.4.1 --- glutin/Cargo.toml | 14 ++- glutin/src/api/cgl/appkit.rs | 162 ++++++++-------------------------- glutin/src/api/cgl/config.rs | 25 +++--- glutin/src/api/cgl/context.rs | 36 ++++---- glutin/src/api/cgl/surface.rs | 45 ++++++---- rustfmt.toml | 2 +- 6 files changed, 113 insertions(+), 171 deletions(-) diff --git a/glutin/Cargo.toml b/glutin/Cargo.toml index 9aed66f29d..ac76b4ad6a 100644 --- a/glutin/Cargo.toml +++ b/glutin/Cargo.toml @@ -52,9 +52,21 @@ x11-dl = { version = "2.20.0", optional = true } [target.'cfg(any(target_os = "macos"))'.dependencies] cgl = "0.3.2" core-foundation = "0.9.3" -objc2 = ">=0.3.0-beta.3, <0.3.0-beta.4" +objc2 = "0.4.1" dispatch = "0.2.0" +[target.'cfg(any(target_os = "macos"))'.dependencies.icrate] +version = "0.0.4" +features = [ + "dispatch", + "Foundation", + "Foundation_NSArray", + "Foundation_NSThread", + "AppKit", + "AppKit_NSView", + "AppKit_NSWindow", +] + [build-dependencies] cfg_aliases = "0.1.1" diff --git a/glutin/src/api/cgl/appkit.rs b/glutin/src/api/cgl/appkit.rs index 33a28da184..88d4ed7eea 100644 --- a/glutin/src/api/cgl/appkit.rs +++ b/glutin/src/api/cgl/appkit.rs @@ -1,46 +1,19 @@ -//! The parts of AppKit related to OpenGL. -//! -//! TODO: Move this to another crate. +//! Parts of AppKit related to OpenGL that is not yet in `icrate`. #![allow(dead_code)] #![allow(non_snake_case)] -use std::ops::Deref; - -use dispatch::Queue; +#[allow(deprecated)] +use icrate::AppKit::{NSOpenGLContextParameter, NSOpenGLPixelFormatAttribute, NSView}; +use icrate::Foundation::{MainThreadMarker, NSObject}; use objc2::encode::{Encoding, RefEncode}; -use objc2::foundation::{is_main_thread, NSInteger, NSObject}; -use objc2::rc::{Id, Shared}; -use objc2::{extern_class, extern_methods, msg_send_id, ClassType}; +use objc2::rc::{Allocated, Id}; +use objc2::{extern_class, extern_methods, mutability, ClassType}; pub type GLint = i32; -pub enum CGLContextObj {} - -// XXX borrowed from winit. - -// Unsafe wrapper type that allows us to dispatch things that aren't Send. -// This should *only* be used to dispatch to the main queue. -// While it is indeed not guaranteed that these types can safely be sent to -// other threads, we know that they're safe to use on the main thread. -pub(crate) struct MainThreadSafe(pub(crate) T); - -unsafe impl Send for MainThreadSafe {} - -impl Deref for MainThreadSafe { - type Target = T; - - fn deref(&self) -> &T { - &self.0 - } -} - -/// Run closure on the main thread. -pub(crate) fn run_on_main(f: impl FnOnce() -> R + Send) -> R { - if is_main_thread() { - f() - } else { - Queue::main().exec_sync(f) - } +#[repr(C)] +pub struct CGLContextObj { + __inner: [u8; 0], } unsafe impl RefEncode for CGLContextObj { @@ -53,6 +26,7 @@ extern_class!( unsafe impl ClassType for NSOpenGLContext { type Super = NSObject; + type Mutability = mutability::InteriorMutable; } ); @@ -61,50 +35,43 @@ unsafe impl Sync for NSOpenGLContext {} extern_methods!( unsafe impl NSOpenGLContext { - pub(crate) fn currentContext() -> Option> { - unsafe { msg_send_id![Self::class(), currentContext] } - } + #[method_id(currentContext)] + pub(crate) fn currentContext() -> Option>; - pub(crate) fn newWithFormat_shareContext( + #[method_id(initWithFormat:shareContext:)] + pub(crate) fn initWithFormat_shareContext( + this: Option>, format: &NSOpenGLPixelFormat, share: Option<&NSOpenGLContext>, - ) -> Option> { - unsafe { - msg_send_id![ - msg_send_id![Self::class(), alloc], - initWithFormat: format, - shareContext: share, - ] - } - } + ) -> Option>; - #[sel(clearCurrentContext)] + #[method(clearCurrentContext)] pub(crate) fn clearCurrentContext(); - #[sel(makeCurrentContext)] + #[method(makeCurrentContext)] pub(crate) fn makeCurrentContext(&self); - #[sel(update)] + #[method(update)] pub(crate) fn update(&self); - #[sel(flushBuffer)] + #[method(flushBuffer)] pub(crate) fn flushBuffer(&self); - pub(crate) fn view(&self) -> Option> { - unsafe { msg_send_id![self, view] } - } + #[method_id(view)] + pub(crate) fn view(&self, mtm: MainThreadMarker) -> Option>; - #[sel(setView:)] - pub(crate) unsafe fn setView(&self, view: Option<&NSObject>); + #[method(setView:)] + pub(crate) unsafe fn setView(&self, view: Option<&NSView>); - #[sel(setValues:forParameter:)] + #[allow(deprecated)] + #[method(setValues:forParameter:)] pub(crate) unsafe fn setValues_forParameter( &self, vals: *const GLint, param: NSOpenGLContextParameter, ); - #[sel(CGLContextObj)] + #[method(CGLContextObj)] pub(crate) fn CGLContextObj(&self) -> *mut CGLContextObj; } ); @@ -115,6 +82,7 @@ extern_class!( unsafe impl ClassType for NSOpenGLPixelFormat { type Super = NSObject; + type Mutability = mutability::Immutable; } ); @@ -123,18 +91,19 @@ unsafe impl Sync for NSOpenGLPixelFormat {} extern_methods!( unsafe impl NSOpenGLPixelFormat { + #[method_id(initWithAttributes:)] + unsafe fn initWithAttributes( + this: Option>, + attrs: *const NSOpenGLPixelFormatAttribute, + ) -> Option>; + pub(crate) unsafe fn newWithAttributes( attrs: &[NSOpenGLPixelFormatAttribute], - ) -> Option> { - unsafe { - msg_send_id![ - msg_send_id![Self::class(), alloc], - initWithAttributes: attrs.as_ptr(), - ] - } + ) -> Option> { + unsafe { Self::initWithAttributes(Self::alloc(), attrs.as_ptr()) } } - #[sel(getValues:forAttribute:forVirtualScreen:)] + #[method(getValues:forAttribute:forVirtualScreen:)] pub(crate) unsafe fn getValues_forAttribute_forVirtualScreen( &self, vals: *mut GLint, @@ -143,60 +112,3 @@ extern_methods!( ); } ); - -type NSOpenGLContextParameter = NSInteger; -pub(crate) const NSOpenGLCPSwapInterval: NSOpenGLContextParameter = 222; -pub(crate) const NSOpenGLCPSurfaceOrder: NSOpenGLContextParameter = 235; -pub(crate) const NSOpenGLCPSurfaceOpacity: NSOpenGLContextParameter = 236; -pub(crate) const NSOpenGLCPSurfaceBackingSize: NSOpenGLContextParameter = 304; -pub(crate) const NSOpenGLCPReclaimResources: NSOpenGLContextParameter = 308; -pub(crate) const NSOpenGLCPCurrentRendererID: NSOpenGLContextParameter = 309; -pub(crate) const NSOpenGLCPGPUVertexProcessing: NSOpenGLContextParameter = 310; -pub(crate) const NSOpenGLCPGPUFragmentProcessing: NSOpenGLContextParameter = 311; -pub(crate) const NSOpenGLCPHasDrawable: NSOpenGLContextParameter = 314; -pub(crate) const NSOpenGLCPMPSwapsInFlight: NSOpenGLContextParameter = 315; - -pub(crate) type NSOpenGLPixelFormatAttribute = u32; -pub(crate) const NSOpenGLPFAAllRenderers: NSOpenGLPixelFormatAttribute = 1; -pub(crate) const NSOpenGLPFATripleBuffer: NSOpenGLPixelFormatAttribute = 3; -pub(crate) const NSOpenGLPFADoubleBuffer: NSOpenGLPixelFormatAttribute = 5; -pub(crate) const NSOpenGLPFAStereo: NSOpenGLPixelFormatAttribute = 6; -pub(crate) const NSOpenGLPFAAuxBuffers: NSOpenGLPixelFormatAttribute = 7; -pub(crate) const NSOpenGLPFAColorSize: NSOpenGLPixelFormatAttribute = 8; -pub(crate) const NSOpenGLPFAAlphaSize: NSOpenGLPixelFormatAttribute = 11; -pub(crate) const NSOpenGLPFADepthSize: NSOpenGLPixelFormatAttribute = 12; -pub(crate) const NSOpenGLPFAStencilSize: NSOpenGLPixelFormatAttribute = 13; -pub(crate) const NSOpenGLPFAAccumSize: NSOpenGLPixelFormatAttribute = 14; -pub(crate) const NSOpenGLPFAMinimumPolicy: NSOpenGLPixelFormatAttribute = 51; -pub(crate) const NSOpenGLPFAMaximumPolicy: NSOpenGLPixelFormatAttribute = 52; -pub(crate) const NSOpenGLPFAOffScreen: NSOpenGLPixelFormatAttribute = 53; -pub(crate) const NSOpenGLPFAFullScreen: NSOpenGLPixelFormatAttribute = 54; -pub(crate) const NSOpenGLPFASampleBuffers: NSOpenGLPixelFormatAttribute = 55; -pub(crate) const NSOpenGLPFASamples: NSOpenGLPixelFormatAttribute = 56; -pub(crate) const NSOpenGLPFAAuxDepthStencil: NSOpenGLPixelFormatAttribute = 57; -pub(crate) const NSOpenGLPFAColorFloat: NSOpenGLPixelFormatAttribute = 58; -pub(crate) const NSOpenGLPFAMultisample: NSOpenGLPixelFormatAttribute = 59; -pub(crate) const NSOpenGLPFASupersample: NSOpenGLPixelFormatAttribute = 60; -pub(crate) const NSOpenGLPFASampleAlpha: NSOpenGLPixelFormatAttribute = 61; -pub(crate) const NSOpenGLPFARendererID: NSOpenGLPixelFormatAttribute = 70; -pub(crate) const NSOpenGLPFASingleRenderer: NSOpenGLPixelFormatAttribute = 71; -pub(crate) const NSOpenGLPFANoRecovery: NSOpenGLPixelFormatAttribute = 72; -pub(crate) const NSOpenGLPFAAccelerated: NSOpenGLPixelFormatAttribute = 73; -pub(crate) const NSOpenGLPFAClosestPolicy: NSOpenGLPixelFormatAttribute = 74; -pub(crate) const NSOpenGLPFARobust: NSOpenGLPixelFormatAttribute = 75; -pub(crate) const NSOpenGLPFABackingStore: NSOpenGLPixelFormatAttribute = 76; -pub(crate) const NSOpenGLPFAMPSafe: NSOpenGLPixelFormatAttribute = 78; -pub(crate) const NSOpenGLPFAWindow: NSOpenGLPixelFormatAttribute = 80; -pub(crate) const NSOpenGLPFAMultiScreen: NSOpenGLPixelFormatAttribute = 81; -pub(crate) const NSOpenGLPFACompliant: NSOpenGLPixelFormatAttribute = 83; -pub(crate) const NSOpenGLPFAScreenMask: NSOpenGLPixelFormatAttribute = 84; -pub(crate) const NSOpenGLPFAPixelBuffer: NSOpenGLPixelFormatAttribute = 90; -pub(crate) const NSOpenGLPFARemotePixelBuffer: NSOpenGLPixelFormatAttribute = 91; -pub(crate) const NSOpenGLPFAAllowOfflineRenderers: NSOpenGLPixelFormatAttribute = 96; -pub(crate) const NSOpenGLPFAAcceleratedCompute: NSOpenGLPixelFormatAttribute = 97; -pub(crate) const NSOpenGLPFAOpenGLProfile: NSOpenGLPixelFormatAttribute = 99; -pub(crate) const NSOpenGLPFAVirtualScreenCount: NSOpenGLPixelFormatAttribute = 128; -// OpenGL Profiles -pub(crate) const NSOpenGLProfileVersionLegacy: NSOpenGLPixelFormatAttribute = 0x1000; -pub(crate) const NSOpenGLProfileVersion3_2Core: NSOpenGLPixelFormatAttribute = 0x3200; -pub(crate) const NSOpenGLProfileVersion4_1Core: NSOpenGLPixelFormatAttribute = 0x4100; diff --git a/glutin/src/api/cgl/config.rs b/glutin/src/api/cgl/config.rs index 7817880989..f1377039fa 100644 --- a/glutin/src/api/cgl/config.rs +++ b/glutin/src/api/cgl/config.rs @@ -3,7 +3,16 @@ use std::sync::Arc; use std::{fmt, iter}; -use objc2::rc::{Id, Shared}; +#[allow(deprecated)] +use icrate::AppKit::{ + NSOpenGLPFAAccelerated, NSOpenGLPFAAllowOfflineRenderers, NSOpenGLPFAAlphaSize, + NSOpenGLPFAColorFloat, NSOpenGLPFAColorSize, NSOpenGLPFADepthSize, NSOpenGLPFADoubleBuffer, + NSOpenGLPFAMinimumPolicy, NSOpenGLPFAMultisample, NSOpenGLPFAOpenGLProfile, + NSOpenGLPFASampleBuffers, NSOpenGLPFASamples, NSOpenGLPFAStencilSize, NSOpenGLPFAStereo, + NSOpenGLPFATripleBuffer, NSOpenGLPixelFormatAttribute, NSOpenGLProfileVersion3_2Core, + NSOpenGLProfileVersion4_1Core, NSOpenGLProfileVersionLegacy, +}; +use objc2::rc::Id; use crate::config::{ Api, AsRawConfig, ColorBufferType, ConfigSurfaceTypes, ConfigTemplate, GlConfig, RawConfig, @@ -12,17 +21,11 @@ use crate::display::GetGlDisplay; use crate::error::{ErrorKind, Result}; use crate::private::Sealed; -use super::appkit::{ - NSOpenGLPFAAccelerated, NSOpenGLPFAAllowOfflineRenderers, NSOpenGLPFAAlphaSize, - NSOpenGLPFAColorFloat, NSOpenGLPFAColorSize, NSOpenGLPFADepthSize, NSOpenGLPFADoubleBuffer, - NSOpenGLPFAMinimumPolicy, NSOpenGLPFAMultisample, NSOpenGLPFAOpenGLProfile, - NSOpenGLPFASampleBuffers, NSOpenGLPFASamples, NSOpenGLPFAStencilSize, NSOpenGLPFAStereo, - NSOpenGLPFATripleBuffer, NSOpenGLPixelFormat, NSOpenGLPixelFormatAttribute, - NSOpenGLProfileVersion3_2Core, NSOpenGLProfileVersion4_1Core, NSOpenGLProfileVersionLegacy, -}; +use super::appkit::NSOpenGLPixelFormat; use super::display::Display; impl Display { + #[allow(deprecated)] pub(crate) unsafe fn find_configs( &self, template: ConfigTemplate, @@ -145,12 +148,14 @@ impl Config { } } + #[allow(deprecated)] pub(crate) fn is_single_buffered(&self) -> bool { self.raw_attribute(NSOpenGLPFATripleBuffer) == 0 && self.raw_attribute(NSOpenGLPFADoubleBuffer) == 0 } } +#[allow(deprecated)] impl GlConfig for Config { fn color_buffer_type(&self) -> Option { // On macos all color formats divide by 3 without reminder, except for the RGB @@ -223,7 +228,7 @@ impl Sealed for Config {} pub(crate) struct ConfigInner { display: Display, pub(crate) transparency: bool, - pub(crate) raw: Id, + pub(crate) raw: Id, } impl PartialEq for ConfigInner { diff --git a/glutin/src/api/cgl/context.rs b/glutin/src/api/cgl/context.rs index 2582f43876..8b4e500a75 100644 --- a/glutin/src/api/cgl/context.rs +++ b/glutin/src/api/cgl/context.rs @@ -4,8 +4,10 @@ use std::fmt; use std::marker::PhantomData; use cgl::CGLSetParameter; -use objc2::foundation::NSObject; -use objc2::rc::{autoreleasepool, Id, Shared}; +use icrate::AppKit::{NSOpenGLCPSwapInterval, NSView}; +use icrate::Foundation::{MainThreadBound, MainThreadMarker}; +use objc2::rc::{autoreleasepool, Id}; +use objc2::ClassType; use crate::config::GetGlConfig; use crate::context::{AsRawContext, ContextApi, ContextAttributes, RawContext, Robustness}; @@ -15,7 +17,7 @@ use crate::prelude::*; use crate::private::Sealed; use crate::surface::{SurfaceTypeTrait, SwapInterval}; -use super::appkit::{run_on_main, MainThreadSafe, NSOpenGLCPSwapInterval, NSOpenGLContext}; +use super::appkit::NSOpenGLContext; use super::config::Config; use super::display::Display; use super::surface::Surface; @@ -42,8 +44,12 @@ impl Display { } let config = config.clone(); - let raw = NSOpenGLContext::newWithFormat_shareContext(&config.inner.raw, share_context) - .ok_or(ErrorKind::BadConfig)?; + let raw = NSOpenGLContext::initWithFormat_shareContext( + NSOpenGLContext::alloc(), + &config.inner.raw, + share_context, + ) + .ok_or(ErrorKind::BadConfig)?; if config.inner.transparency { let opacity = 0; @@ -200,7 +206,7 @@ impl Sealed for PossiblyCurrentContext {} pub(crate) struct ContextInner { display: Display, config: Config, - pub(crate) raw: Id, + pub(crate) raw: Id, } impl ContextInner { @@ -216,11 +222,10 @@ impl ContextInner { autoreleasepool(|_| { self.update(); self.raw.makeCurrentContext(); - let raw = MainThreadSafe(&self.raw); - let ns_view = MainThreadSafe(&surface.ns_view); - run_on_main(move || unsafe { - raw.setView(Some(*ns_view)); + let view = &surface.ns_view; + MainThreadMarker::run_on_main(|mtm| unsafe { + self.raw.setView(Some(&view.get(mtm))); }); Ok(()) @@ -243,10 +248,7 @@ impl ContextInner { } pub(crate) fn update(&self) { - let raw = MainThreadSafe(&self.raw); - run_on_main(move || { - raw.update(); - }); + MainThreadMarker::run_on_main(|_| self.raw.update()); } pub(crate) fn flush_buffer(&self) -> Result<()> { @@ -256,8 +258,10 @@ impl ContextInner { }) } - pub(crate) fn current_view(&self) -> Id { - self.raw.view().expect("context to have a current view") + pub(crate) fn is_view_current(&self, view: &MainThreadBound>) -> bool { + MainThreadMarker::run_on_main(|mtm| { + self.raw.view(mtm).expect("context to have a current view") == *view.get(mtm) + }) } fn make_not_current(&self) -> Result<()> { diff --git a/glutin/src/api/cgl/surface.rs b/glutin/src/api/cgl/surface.rs index 3b22d4552b..05dbff495a 100644 --- a/glutin/src/api/cgl/surface.rs +++ b/glutin/src/api/cgl/surface.rs @@ -4,9 +4,9 @@ use std::fmt; use std::marker::PhantomData; use std::num::NonZeroU32; -use objc2::foundation::{CGFloat, NSObject, NSRect}; -use objc2::msg_send; -use objc2::rc::{Id, Shared}; +use icrate::AppKit::{NSView, NSWindow}; +use icrate::Foundation::{MainThreadBound, MainThreadMarker}; +use objc2::rc::Id; use raw_window_handle::RawWindowHandle; use crate::config::GetGlConfig; @@ -18,7 +18,6 @@ use crate::surface::{ SurfaceTypeTrait, SwapInterval, WindowSurface, }; -use super::appkit::{run_on_main, MainThreadSafe}; use super::config::Config; use super::context::PossiblyCurrentContext; use super::display::Display; @@ -54,6 +53,10 @@ impl Display { }, }; + // SAFETY: The objects below must have been created on the main thread + // in the first place, so we can safely "move" them back to that thread. + let mtm = unsafe { MainThreadMarker::new_unchecked() }; + // SAFETY: Validity of the view and window is ensured by caller // This function makes sure the window is non null. let ns_view = if let Some(ns_view) = unsafe { Id::retain(native_window.ns_view.cast()) } { @@ -61,6 +64,7 @@ impl Display { } else { return Err(ErrorKind::NotSupported("ns_view of provided native window is nil").into()); }; + let ns_view = MainThreadBound::new(ns_view, mtm); let ns_window = if let Some(ns_window) = unsafe { Id::retain(native_window.ns_window.cast()) } @@ -69,12 +73,14 @@ impl Display { } else { return Err(ErrorKind::NotSupported("ns_view of provided native window is nil").into()); }; + let ns_window = MainThreadBound::new(ns_window, mtm); let surface = Surface { display: self.clone(), config: config.clone(), ns_view, ns_window, + _nosendsync: PhantomData, _ty: PhantomData, }; Ok(surface) @@ -85,8 +91,9 @@ impl Display { pub struct Surface { display: Display, config: Config, - pub(crate) ns_view: Id, - ns_window: Id, + pub(crate) ns_view: MainThreadBound>, + ns_window: MainThreadBound>, + _nosendsync: PhantomData<*const std::ffi::c_void>, _ty: PhantomData, } @@ -99,21 +106,21 @@ impl GlSurface for Surface { } fn width(&self) -> Option { - let ns_window = MainThreadSafe(&self.ns_window); - let ns_view = MainThreadSafe(&self.ns_view); - run_on_main(move || unsafe { - let scale_factor: CGFloat = msg_send![*ns_window, backingScaleFactor]; - let frame: NSRect = msg_send![*ns_view, frame]; + let window = &self.ns_window; + let view = &self.ns_view; + MainThreadMarker::run_on_main(|mtm| unsafe { + let scale_factor = window.get(mtm).backingScaleFactor(); + let frame = view.get(mtm).frame(); Some((frame.size.width * scale_factor) as u32) }) } fn height(&self) -> Option { - let ns_window = MainThreadSafe(&self.ns_window); - let ns_view = MainThreadSafe(&self.ns_view); - run_on_main(move || unsafe { - let scale_factor: CGFloat = msg_send![*ns_window, backingScaleFactor]; - let frame: NSRect = msg_send![*ns_view, frame]; + let window = &self.ns_window; + let view = &self.ns_view; + MainThreadMarker::run_on_main(|mtm| unsafe { + let scale_factor = window.get(mtm).backingScaleFactor(); + let frame = view.get(mtm).frame(); Some((frame.size.height * scale_factor) as u32) }) } @@ -132,7 +139,7 @@ impl GlSurface for Surface { } fn is_current(&self, context: &Self::Context) -> bool { - self.ns_view == context.inner.current_view() + context.inner.is_view_current(&self.ns_view) } fn is_current_draw(&self, context: &Self::Context) -> bool { @@ -166,7 +173,9 @@ impl GetGlDisplay for Surface { impl AsRawSurface for Surface { fn raw_surface(&self) -> RawSurface { - RawSurface::Cgl(Id::as_ptr(&self.ns_view).cast()) + // SAFETY: We only use the thread marker to get the pointer value of the view + let mtm = unsafe { MainThreadMarker::new_unchecked() }; + RawSurface::Cgl(Id::as_ptr(&self.ns_view.get(mtm)).cast()) } } diff --git a/rustfmt.toml b/rustfmt.toml index 8057fee246..a47427eb44 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -7,7 +7,7 @@ overflow_delimited_expr = true imports_granularity = "Module" use_small_heuristics = "Max" normalize_comments = true -reorder_impl_items = true +# reorder_impl_items = true # Currently breaks objc2::declare_class! use_try_shorthand = true newline_style = "Unix" format_strings = true