diff --git a/src/native/apple/frameworks.rs b/src/native/apple/frameworks.rs
index d4a1c22c..c5b7985a 100644
--- a/src/native/apple/frameworks.rs
+++ b/src/native/apple/frameworks.rs
@@ -238,6 +238,65 @@ extern "C" {
pub fn MTLCopyAllDevices() -> ObjcId; //TODO: Array
}
+#[cfg(target_os = "macos")]
+#[repr(C)]
+#[derive(Clone, Copy, Debug)]
+pub struct CVTime {
+ pub time_value: i64,
+ pub time_scale: i32,
+ pub flags: i32,
+ pub epoch: i64,
+}
+
+#[cfg(target_os = "macos")]
+pub type CVDisplayLinkRef = *mut c_void;
+
+#[cfg(target_os = "macos")]
+pub type CVOptionFlags = u64;
+
+#[cfg(target_os = "macos")]
+#[repr(C)]
+#[derive(Clone, Copy, Debug)]
+pub struct CVTimeStamp {
+ pub version: u32,
+ pub video_time_scale: i32,
+ pub video_time: i64,
+ pub host_time: u64,
+ pub rate_scalar: f64,
+ pub video_refresh_period: i64,
+ pub smpte_time: i64,
+ pub flags: u64,
+ pub reserved: u64,
+}
+
+#[cfg(target_os = "macos")]
+pub type CVDisplayLinkOutputCallback = extern "C" fn(
+ display_link: CVDisplayLinkRef,
+ now: *const CVTimeStamp,
+ output_time: *const CVTimeStamp,
+ flags_in: CVOptionFlags,
+ flags_out: *mut CVOptionFlags,
+ display_link_context: *mut c_void,
+) -> i32;
+
+#[cfg(target_os = "macos")]
+pub const kCVTimeIsIndefinite: i32 = 1 << 0;
+
+#[cfg(target_os = "macos")]
+#[link(name = "CoreVideo", kind = "framework")]
+extern "C" {
+ pub fn CVDisplayLinkCreateWithActiveCGDisplays(display_link_out: *mut CVDisplayLinkRef) -> i32;
+ pub fn CVDisplayLinkSetOutputCallback(
+ display_link: CVDisplayLinkRef,
+ callback: CVDisplayLinkOutputCallback,
+ user_info: *mut c_void,
+ ) -> i32;
+ pub fn CVDisplayLinkStart(display_link: CVDisplayLinkRef) -> i32;
+ pub fn CVDisplayLinkStop(display_link: CVDisplayLinkRef) -> i32;
+ pub fn CVDisplayLinkRelease(display_link: CVDisplayLinkRef);
+ pub fn CVDisplayLinkGetNominalOutputVideoRefreshPeriod(display_link: CVDisplayLinkRef) -> CVTime;
+}
+
// Foundation
#[repr(C)]
diff --git a/src/native/macos.rs b/src/native/macos.rs
index 29b3e2ef..744a88b3 100644
--- a/src/native/macos.rs
+++ b/src/native/macos.rs
@@ -15,7 +15,10 @@ use {
std::{
collections::HashMap,
os::raw::c_void,
- sync::mpsc::Receiver,
+ sync::{
+ Condvar, Mutex,
+ mpsc::Receiver,
+ },
time::{Duration, Instant},
},
};
@@ -994,7 +997,9 @@ unsafe fn create_opengl_view(
display.gl_context = msg_send![gl_context, initWithFormat: glpixelformat_obj shareContext: nil];
- let mut swap_interval = 1;
+ // Set the swap interval to 0 to disable vsync, because we're using CVDisplayLink for frame pacing
+ // and we don't want to have an extra vsync delay on top of that.
+ let mut swap_interval = 0;
let () = msg_send![display.gl_context,
setValues:&mut swap_interval
forParameter:NSOpenGLContextParameterSwapInterval];
@@ -1016,6 +1021,97 @@ impl crate::native::Clipboard for MacosClipboard {
fn set(&mut self, _data: &str) {}
}
+struct FrameSignal {
+ frame_ready: Mutex