diff --git a/Cargo.lock b/Cargo.lock index 9333a6c7..215c4503 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1398,13 +1398,16 @@ version = "0.1.0" dependencies = [ "cbindgen 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", "font-kit 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "metal 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_canvas 0.1.0", "pathfinder_content 0.1.0", "pathfinder_geometry 0.3.0", "pathfinder_gl 0.1.0", "pathfinder_gpu 0.1.0", + "pathfinder_metal 0.1.0", "pathfinder_renderer 0.1.0", "pathfinder_simd 0.3.0", ] diff --git a/c/Cargo.toml b/c/Cargo.toml index a4ea30e5..e1c0eb0b 100644 --- a/c/Cargo.toml +++ b/c/Cargo.toml @@ -10,6 +10,7 @@ crate-type = ["staticlib"] [dependencies] font-kit = "0.2" +foreign-types = "0.3" gl = "0.6" libc = "0.2" @@ -34,5 +35,11 @@ path = "../renderer" [dependencies.pathfinder_simd] path = "../simd" +[target.'cfg(target_os = "macos")'.dependencies] +metal = "0.14" + +[target.'cfg(target_os = "macos")'.dependencies.pathfinder_metal] +path = "../metal" + [build-dependencies] cbindgen = "0.8" diff --git a/c/src/lib.rs b/c/src/lib.rs index b8403638..6b6235c1 100644 --- a/c/src/lib.rs +++ b/c/src/lib.rs @@ -11,6 +11,7 @@ //! C bindings to Pathfinder. use font_kit::handle::Handle; +use foreign_types::ForeignTypeRef; use gl; use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, FillStyle, LineJoin}; use pathfinder_canvas::{Path2D, TextMetrics}; @@ -33,6 +34,11 @@ use std::os::raw::{c_char, c_void}; use std::slice; use std::str; +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +use metal::{CAMetalLayer, CoreAnimationLayerRef}; +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +use pathfinder_metal::MetalDevice; + // Constants // `canvas` @@ -118,10 +124,18 @@ pub type PFGLFunctionLoader = extern "C" fn(name: *const c_char, userdata: *mut // `gpu` pub type PFGLDestFramebufferRef = *mut DestFramebuffer; pub type PFGLRendererRef = *mut Renderer; +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +pub type PFMetalDestFramebufferRef = *mut DestFramebuffer; +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +pub type PFMetalRendererRef = *mut Renderer; // FIXME(pcwalton): Double-boxing is unfortunate. Remove this when `std::raw::TraitObject` is // stable? pub type PFResourceLoaderRef = *mut Box; +// `metal` +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +pub type PFMetalDeviceRef = *mut MetalDevice; + // `renderer` pub type PFSceneRef = *mut Scene; pub type PFSceneProxyRef = *mut SceneProxy; @@ -456,6 +470,46 @@ pub unsafe extern "C" fn PFGLRendererGetDevice(renderer: PFGLRendererRef) -> PFG &mut (*renderer).device } +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFMetalDestFramebufferCreateFullWindow(window_size: *const PFVector2I) + -> PFMetalDestFramebufferRef { + Box::into_raw(Box::new(DestFramebuffer::full_window((*window_size).to_rust()))) +} + +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFMetalDestFramebufferDestroy(dest_framebuffer: + PFMetalDestFramebufferRef) { + drop(Box::from_raw(dest_framebuffer)) +} + +/// Takes ownership of `device` and `dest_framebuffer`, but not `resources`. +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFMetalRendererCreate(device: PFMetalDeviceRef, + resources: PFResourceLoaderRef, + dest_framebuffer: PFMetalDestFramebufferRef, + options: *const PFRendererOptions) + -> PFMetalRendererRef { + Box::into_raw(Box::new(Renderer::new(*Box::from_raw(device), + &**resources, + *Box::from_raw(dest_framebuffer), + (*options).to_rust()))) +} + +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFMetalRendererDestroy(renderer: PFMetalRendererRef) { + drop(Box::from_raw(renderer)) +} + +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFMetalRendererGetDevice(renderer: PFMetalRendererRef) -> PFMetalDeviceRef { + &mut (*renderer).device +} + #[no_mangle] pub unsafe extern "C" fn PFSceneProxyBuildAndRenderGL(scene_proxy: PFSceneProxyRef, renderer: PFGLRendererRef, @@ -463,6 +517,29 @@ pub unsafe extern "C" fn PFSceneProxyBuildAndRenderGL(scene_proxy: PFSceneProxyR (*scene_proxy).build_and_render(&mut *renderer, (*build_options).to_rust()) } +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFSceneProxyBuildAndRenderMetal(scene_proxy: PFSceneProxyRef, + renderer: PFMetalRendererRef, + build_options: *const PFBuildOptions) { + (*scene_proxy).build_and_render(&mut *renderer, (*build_options).to_rust()) +} + +// `metal` + +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFMetalDeviceCreate(layer: *mut CAMetalLayer) + -> PFMetalDeviceRef { + Box::into_raw(Box::new(MetalDevice::new(CoreAnimationLayerRef::from_ptr(layer)))) +} + +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFMetalDeviceDestroy(device: PFMetalDeviceRef) { + drop(Box::from_raw(device)) +} + // `renderer` #[no_mangle] diff --git a/examples/c_canvas_minimal/Makefile b/examples/c_canvas_minimal/Makefile index 14563401..d2c8a5dc 100644 --- a/examples/c_canvas_minimal/Makefile +++ b/examples/c_canvas_minimal/Makefile @@ -15,7 +15,7 @@ UNAME=$(shell uname -s) ifeq ($(UNAME),Darwin) # FIXME(pcwalton): Don't link against HarfBuzz!! LIBS+=-framework OpenGL -framework CoreFoundation -framework CoreGraphics -framework CoreText - LIBS+=-lharfbuzz + LIBS+=-framework Metal -lharfbuzz else LIBS+=-lGL endif