diff --git a/Cargo.lock b/Cargo.lock index 7dff1a8bb834c5c5cb30facd056e84bc7b3d8d82..4f6f6fe8392c68e5b41b7c84f19e9207e0994306 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -762,6 +762,7 @@ dependencies = [ "core-graphics", "foreign-types", "gpui", + "io_surface", "log", "objc", "simplelog", @@ -2228,6 +2229,7 @@ dependencies = [ "futures", "gpui_macros", "image", + "io_surface", "lazy_static", "log", "metal", @@ -2596,6 +2598,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "io_surface" +version = "0.1.0" +dependencies = [ + "block", + "core-foundation", + "objc", +] + [[package]] name = "iovec" version = "0.1.4" diff --git a/crates/capture/Cargo.toml b/crates/capture/Cargo.toml index aade52f2fbc9a561bd9856e538e9edb5d80a21f9..ebb35d8ef2203d6feb7a55dc7c0b6b286d56b421 100644 --- a/crates/capture/Cargo.toml +++ b/crates/capture/Cargo.toml @@ -10,6 +10,7 @@ identifier = "dev.zed.Capture" [dependencies] gpui = { path = "../gpui" } +io_surface = { path = "../io_surface" } block = "0.1" cocoa = "0.24" diff --git a/crates/capture/build.rs b/crates/capture/build.rs index a375d48f48670e912697c17181300643ebdf02c6..8e95dca2ff3d47021a6b7cd3ceb9d1945151bc08 100644 --- a/crates/capture/build.rs +++ b/crates/capture/build.rs @@ -24,8 +24,9 @@ fn main() { .allowlist_function("CMTimeMake") .allowlist_type("SCStreamOutputType") .allowlist_type("SCFrameStatus") + .allowlist_type("dispatch_queue_t") .allowlist_var("SCStreamFrameInfo.*") - .allowlist_function("dispatch_queue_create") + .allowlist_var("_dispatch_main_q") .parse_callbacks(Box::new(bindgen::CargoCallbacks)) .layout_tests(false) .generate() diff --git a/crates/capture/src/bindings.rs b/crates/capture/src/bindings.rs index a111bede4de059f0c0157775778bcc56ebdd4079..68487fce3250d90578264e681be0679c275ad4c9 100644 --- a/crates/capture/src/bindings.rs +++ b/crates/capture/src/bindings.rs @@ -1,7 +1,12 @@ #![allow(non_upper_case_globals)] #![allow(non_camel_case_types)] #![allow(non_snake_case)] +#![allow(unused)] use objc::*; include!(concat!(env!("OUT_DIR"), "/bindings.rs")); + +pub fn dispatch_get_main_queue() -> dispatch_queue_t { + unsafe { std::mem::transmute(&_dispatch_main_q) } +} diff --git a/crates/capture/src/main.rs b/crates/capture/src/main.rs index ac785a8d85141d965cdbbe65c386165523e76eac..94561bde7e78aa517c34e2d0920d41c43977a311 100644 --- a/crates/capture/src/main.rs +++ b/crates/capture/src/main.rs @@ -1,6 +1,6 @@ mod bindings; -use crate::bindings::{dispatch_queue_create, NSObject, SCStreamOutputType}; +use crate::bindings::{dispatch_get_main_queue, SCStreamOutputType}; use block::ConcreteBlock; use cocoa::{ base::{id, nil, YES}, @@ -8,6 +8,7 @@ use cocoa::{ }; use core_foundation::{base::TCFType, number::CFNumberRef, string::CFStringRef}; use core_media::{CMSampleBuffer, CMSampleBufferRef}; +use gpui::elements::Canvas; use gpui::{actions, elements::*, keymap::Binding, Menu, MenuItem}; use log::LevelFilter; use objc::{ @@ -18,7 +19,7 @@ use objc::{ sel, sel_impl, }; use simplelog::SimpleLogger; -use std::{ptr, slice, str}; +use std::{ffi::c_void, slice, str}; #[allow(non_upper_case_globals)] const NSUTF8StringEncoding: NSUInteger = 4; @@ -55,11 +56,17 @@ fn main() { let display_height: usize = msg_send![display, height]; let mut decl = ClassDecl::new("CaptureOutput", class!(NSObject)).unwrap(); + decl.add_ivar::<*mut c_void>("callback"); decl.add_method(sel!(stream:didOutputSampleBuffer:ofType:), sample_output as extern "C" fn(&Object, Sel, id, id, SCStreamOutputType)); let capture_output_class = decl.register(); let output: id = msg_send![capture_output_class, alloc]; let output: id = msg_send![output, init]; + let callback = Box::new(|buffer: CMSampleBufferRef| { + dbg!("HEY!"); + }) as Box; + let callback = Box::into_raw(Box::new(callback)); + (*output).set_ivar("callback", callback as *mut c_void); let filter: id = msg_send![class!(SCContentFilter), alloc]; let filter: id = msg_send![filter, initWithDisplay: display includingApplications: applications exceptingWindows: nil]; @@ -75,7 +82,7 @@ fn main() { let stream: id = msg_send![class!(SCStream), alloc]; let stream: id = msg_send![stream, initWithFilter: filter configuration: config delegate: output]; let error: id = nil; - let queue = dispatch_queue_create(ptr::null(), NSObject(ptr::null_mut())); + let queue = dispatch_get_main_queue(); let _: () = msg_send![stream, addStreamOutput: output type: bindings::SCStreamOutputType_SCStreamOutputTypeScreen @@ -107,19 +114,29 @@ fn main() { }); } -struct ScreenCaptureView; +struct ScreenCaptureView { + surface: io_surface::IOSurface, +} impl gpui::Entity for ScreenCaptureView { type Event = (); } +// impl ScreenCaptureView { +// pub fn new() -> Self {} +// } + impl gpui::View for ScreenCaptureView { fn ui_name() -> &'static str { "View" } fn render(&mut self, _: &mut gpui::RenderContext) -> gpui::ElementBox { - Empty::new().boxed() + Canvas::new(|bounds, _, cx| { + + // cx.scene.push_surface(surface) + }) + .boxed() } } @@ -136,13 +153,18 @@ pub unsafe fn string_from_objc(string: id) -> String { } extern "C" fn sample_output( - _: &Object, + this: &Object, _: Sel, _stream: id, buffer: id, _kind: SCStreamOutputType, ) { let buffer = unsafe { CMSampleBuffer::wrap_under_get_rule(buffer as CMSampleBufferRef) }; + let callback = unsafe { *this.get_ivar::<*mut c_void>("callback") }; + let callback = callback as *mut Box; + let x = unsafe { callback.as_mut().unwrap() }; + (*x)(buffer.as_concrete_TypeRef()); + let attachments = buffer.attachments(); let attachments = attachments.first().expect("no attachments for sample"); @@ -228,11 +250,11 @@ mod core_media { mod core_video { #![allow(non_snake_case)] - use crate::io_surface::{IOSurface, IOSurfaceRef}; use core_foundation::{ base::{CFTypeID, TCFType}, declare_TCFType, impl_CFTypeDescription, impl_TCFType, }; + use io_surface::{IOSurface, IOSurfaceRef}; use std::ffi::c_void; #[repr(C)] @@ -269,26 +291,3 @@ mod core_video { fn CVPixelBufferGetHeight(buffer: CVImageBufferRef) -> usize; } } - -mod io_surface { - #![allow(non_snake_case)] - - use core_foundation::{ - base::{CFTypeID, TCFType}, - declare_TCFType, impl_CFTypeDescription, impl_TCFType, - }; - use std::ffi::c_void; - - #[repr(C)] - pub struct __IOSurface(c_void); - // The ref type must be a pointer to the underlying struct. - pub type IOSurfaceRef = *const __IOSurface; - - declare_TCFType!(IOSurface, IOSurfaceRef); - impl_TCFType!(IOSurface, IOSurfaceRef, IOSurfaceGetTypeID); - impl_CFTypeDescription!(IOSurface); - - extern "C" { - fn IOSurfaceGetTypeID() -> CFTypeID; - } -} diff --git a/crates/gpui/Cargo.toml b/crates/gpui/Cargo.toml index 08c32135fb5170644033232e20ae9859128e81b2..6539c292fca18b6e25d0cc93d86242e1eba01bda 100644 --- a/crates/gpui/Cargo.toml +++ b/crates/gpui/Cargo.toml @@ -60,6 +60,7 @@ png = "0.16" simplelog = "0.9" [target.'cfg(target_os = "macos")'.dependencies] +io_surface = { path = "../io_surface" } anyhow = "1" block = "0.1" cocoa = "0.24" diff --git a/crates/gpui/build.rs b/crates/gpui/build.rs index 967423d3f73297ecb9a48b11558c3e364a3173f8..836d586c26bea742d7b31832d0b17b64d0295a05 100644 --- a/crates/gpui/build.rs +++ b/crates/gpui/build.rs @@ -19,7 +19,6 @@ fn generate_dispatch_bindings() { .header("src/platform/mac/dispatch.h") .allowlist_var("_dispatch_main_q") .allowlist_function("dispatch_async_f") - .allowlist_function("dispatch_queue_create") .parse_callbacks(Box::new(bindgen::CargoCallbacks)) .layout_tests(false) .generate() diff --git a/crates/gpui/src/platform/mac.rs b/crates/gpui/src/platform/mac.rs index 4ff73fcff28b36c1ff6509ae1e79eb5027aa6f45..c1a4d45561dae5307a0f628588c37b8977809a61 100644 --- a/crates/gpui/src/platform/mac.rs +++ b/crates/gpui/src/platform/mac.rs @@ -1,5 +1,5 @@ mod atlas; -pub mod dispatcher; +mod dispatcher; mod event; mod fonts; mod geometry; diff --git a/crates/gpui/src/platform/mac/renderer.rs b/crates/gpui/src/platform/mac/renderer.rs index 711d9e48b54e1026e81fe4d41391015f25c8aaaa..25870c81fbf47243f1cbaaa6b1ae3c93ebbeb477 100644 --- a/crates/gpui/src/platform/mac/renderer.rs +++ b/crates/gpui/src/platform/mac/renderer.rs @@ -39,6 +39,7 @@ struct PathSprite { pub struct Surface { pub bounds: RectF, + pub native_surface: io_surface::IOSurface, } impl Renderer { diff --git a/crates/io_surface/Cargo.toml b/crates/io_surface/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..2d9324b6d8951def6dd62d82d728479b2f6226e0 --- /dev/null +++ b/crates/io_surface/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "io_surface" +version = "0.1.0" +edition = "2021" + +[lib] +path = "src/io_surface.rs" +doctest = false + +[dependencies] +block = "0.1" +core-foundation = "0.9.3" +objc = "0.2" \ No newline at end of file diff --git a/crates/io_surface/src/io_surface.rs b/crates/io_surface/src/io_surface.rs new file mode 100644 index 0000000000000000000000000000000000000000..13b1fd5ce1f7f8e64102d60210ae24ffd6914460 --- /dev/null +++ b/crates/io_surface/src/io_surface.rs @@ -0,0 +1,21 @@ +#![allow(non_snake_case)] + +use core_foundation::{ + base::{CFTypeID, TCFType}, + declare_TCFType, impl_CFTypeDescription, impl_TCFType, +}; +use std::ffi::c_void; + +#[repr(C)] +pub struct __IOSurface(c_void); +// The ref type must be a pointer to the underlying struct. +pub type IOSurfaceRef = *const __IOSurface; + +declare_TCFType!(IOSurface, IOSurfaceRef); +impl_TCFType!(IOSurface, IOSurfaceRef, IOSurfaceGetTypeID); +impl_CFTypeDescription!(IOSurface); + +#[link(name = "IOSurface", kind = "framework")] +extern "C" { + fn IOSurfaceGetTypeID() -> CFTypeID; +}