From a8d20cb37f716b9707134a175bec741ea2955393 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 24 Jun 2019 14:03:26 -0700 Subject: [PATCH] Add transform support to the C API, and fix build problems --- c/cbindgen.toml | 12 +- c/src/lib.rs | 155 ++++++++++++++++--- examples/c_canvas_minimal/c_canvas_minimal.c | 2 +- geometry/src/transform2d.rs | 4 +- 4 files changed, 148 insertions(+), 25 deletions(-) diff --git a/c/cbindgen.toml b/c/cbindgen.toml index 4d096e5d..16bd9b2a 100644 --- a/c/cbindgen.toml +++ b/c/cbindgen.toml @@ -2,18 +2,28 @@ language = "C" header = """\ /* Generated code. Do not edit; instead run `cargo build` in `pathfinder_c`. */ +#ifdef __cplusplus extern \"C\" { +#endif +""" +trailer = """\ +#ifdef __cplusplus +} +#endif """ -trailer = "}" include_guard = "PF_PATHFINDER_H" include_version = true [parse] parse_deps = true include = [ + "font-kit", + "metal", "pathfinder_canvas", "pathfinder_content", "pathfinder_geometry", "pathfinder_gl", + "pathfinder_gpu", + "pathfinder_metal", "pathfinder_renderer", ] diff --git a/c/src/lib.rs b/c/src/lib.rs index 7b2e2ef9..079a4f26 100644 --- a/c/src/lib.rs +++ b/c/src/lib.rs @@ -19,6 +19,8 @@ use pathfinder_content::color::{ColorF, ColorU}; use pathfinder_content::outline::ArcDirection; use pathfinder_content::stroke::LineCap; use pathfinder_geometry::rect::{RectF, RectI}; +use pathfinder_geometry::transform2d::{Matrix2x2F, Transform2DF}; +use pathfinder_geometry::transform3d::{Perspective, Transform3DF}; use pathfinder_geometry::vector::{Vector2F, Vector2I}; use pathfinder_gl::{GLDevice, GLVersion}; use pathfinder_gpu::resources::{FilesystemResourceLoader, ResourceLoader}; @@ -26,7 +28,7 @@ use pathfinder_renderer::concurrent::rayon::RayonExecutor; use pathfinder_renderer::concurrent::scene_proxy::SceneProxy; use pathfinder_renderer::gpu::options::{DestFramebuffer, RendererOptions}; use pathfinder_renderer::gpu::renderer::Renderer; -use pathfinder_renderer::options::BuildOptions; +use pathfinder_renderer::options::{BuildOptions, RenderTransform}; use pathfinder_renderer::scene::Scene; use pathfinder_simd::default::F32x4; use std::ffi::CString; @@ -60,6 +62,11 @@ pub const PF_TEXT_ALIGN_RIGHT: u8 = 2; pub const PF_ARC_DIRECTION_CW: u8 = 0; pub const PF_ARC_DIRECTION_CCW: u8 = 1; +// `gl` + +pub const PF_GL_VERSION_GL3: u8 = 0; +pub const PF_GL_VERSION_GLES3: u8 = 1; + // `renderer` pub const PF_RENDERER_OPTIONS_FLAGS_HAS_BACKGROUND_COLOR: u8 = 0x1; @@ -120,10 +127,35 @@ pub struct PFRectI { pub origin: PFVector2I, pub lower_right: PFVector2I, } +/// Row-major order. +#[repr(C)] +pub struct PFMatrix2x2F { + pub m00: f32, pub m01: f32, + pub m10: f32, pub m11: f32, +} +/// Row-major order. +#[repr(C)] +pub struct PFTransform2DF { + pub matrix: PFMatrix2x2F, + pub vector: PFVector2F, +} +/// Row-major order. +#[repr(C)] +pub struct PFTransform3DF { + pub m00: f32, pub m01: f32, pub m02: f32, pub m03: f32, + pub m10: f32, pub m11: f32, pub m12: f32, pub m13: f32, + pub m20: f32, pub m21: f32, pub m22: f32, pub m23: f32, + pub m30: f32, pub m31: f32, pub m32: f32, pub m33: f32, +} +#[repr(C)] +pub struct PFPerspective { + pub transform: PFTransform3DF, + pub window_size: PFVector2I, +} // `gl` pub type PFGLDeviceRef = *mut GLDevice; -pub type PFGLVersion = GLVersion; +pub type PFGLVersion = u8; pub type PFGLFunctionLoader = extern "C" fn(name: *const c_char, userdata: *mut c_void) -> *const c_void; // `gpu` @@ -135,7 +167,8 @@ pub type PFMetalDestFramebufferRef = *mut DestFramebuffer; pub type PFMetalRendererRef = *mut Renderer; // FIXME(pcwalton): Double-boxing is unfortunate. Remove this when `std::raw::TraitObject` is // stable? -pub type PFResourceLoaderRef = *mut Box; +pub type PFResourceLoaderRef = *mut ResourceLoaderWrapper; +pub struct ResourceLoaderWrapper(Box); // `metal` #[cfg(all(target_os = "macos", not(feature = "pf-gl")))] @@ -150,11 +183,8 @@ pub struct PFRendererOptions { pub flags: PFRendererOptionsFlags, } pub type PFRendererOptionsFlags = u8; -// TODO(pcwalton) -#[repr(C)] -pub struct PFBuildOptions { - pub placeholder: u32, -} +pub type PFBuildOptionsRef = *mut BuildOptions; +pub type PFRenderTransformRef = *mut RenderTransform; // `canvas` @@ -421,7 +451,7 @@ pub unsafe extern "C" fn PFFillStyleDestroy(fill_style: PFFillStyleRef) { #[no_mangle] pub unsafe extern "C" fn PFFilesystemResourceLoaderLocate() -> PFResourceLoaderRef { let loader = Box::new(FilesystemResourceLoader::locate()); - Box::into_raw(Box::new(loader as Box)) + Box::into_raw(Box::new(ResourceLoaderWrapper(loader as Box))) } #[no_mangle] @@ -435,6 +465,7 @@ pub unsafe extern "C" fn PFGLLoadWith(loader: PFGLFunctionLoader, userdata: *mut #[no_mangle] pub unsafe extern "C" fn PFGLDeviceCreate(version: PFGLVersion, default_framebuffer: u32) -> PFGLDeviceRef { + let version = match version { PF_GL_VERSION_GLES3 => GLVersion::GLES3, _ => GLVersion::GL3 }; Box::into_raw(Box::new(GLDevice::new(version, default_framebuffer))) } @@ -469,7 +500,7 @@ pub unsafe extern "C" fn PFGLRendererCreate(device: PFGLDeviceRef, options: *const PFRendererOptions) -> PFGLRendererRef { Box::into_raw(Box::new(Renderer::new(*Box::from_raw(device), - &**resources, + &*((*resources).0), *Box::from_raw(dest_framebuffer), (*options).to_rust()))) } @@ -507,7 +538,7 @@ pub unsafe extern "C" fn PFMetalRendererCreate(device: PFMetalDeviceRef, options: *const PFRendererOptions) -> PFMetalRendererRef { Box::into_raw(Box::new(Renderer::new(*Box::from_raw(device), - &**resources, + &*((*resources).0), *Box::from_raw(dest_framebuffer), (*options).to_rust()))) } @@ -524,19 +555,21 @@ pub unsafe extern "C" fn PFMetalRendererGetDevice(renderer: PFMetalRendererRef) &mut (*renderer).device } +// Consumes `build_options`. #[no_mangle] pub unsafe extern "C" fn PFSceneProxyBuildAndRenderGL(scene_proxy: PFSceneProxyRef, renderer: PFGLRendererRef, - build_options: *const PFBuildOptions) { - (*scene_proxy).build_and_render(&mut *renderer, (*build_options).to_rust()) + build_options: PFBuildOptionsRef) { + (*scene_proxy).build_and_render(&mut *renderer, *Box::from_raw(build_options)) } +// Consumes `build_options`. #[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()) + build_options: PFBuildOptionsRef) { + (*scene_proxy).build_and_render(&mut *renderer, *Box::from_raw(build_options)) } // `metal` @@ -554,8 +587,60 @@ pub unsafe extern "C" fn PFMetalDeviceDestroy(device: PFMetalDeviceRef) { drop(Box::from_raw(device)) } +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFMetalDevicePresentDrawable(device: PFMetalDeviceRef) { + (*device).present_drawable() +} + // `renderer` +#[no_mangle] +pub unsafe extern "C" fn PFRenderTransformCreate2D(transform: *const PFTransform2DF) + -> PFRenderTransformRef { + Box::into_raw(Box::new(RenderTransform::Transform2D((*transform).to_rust()))) +} + +#[no_mangle] +pub unsafe extern "C" fn PFRenderTransformCreatePerspective(perspective: *const PFPerspective) + -> PFRenderTransformRef { + Box::into_raw(Box::new(RenderTransform::Perspective((*perspective).to_rust()))) +} + +#[no_mangle] +pub unsafe extern "C" fn PFRenderTransformDestroy(transform: PFRenderTransformRef) { + drop(Box::from_raw(transform)) +} + +#[no_mangle] +pub unsafe extern "C" fn PFBuildOptionsCreate() -> PFBuildOptionsRef { + Box::into_raw(Box::new(BuildOptions::default())) +} + +#[no_mangle] +pub unsafe extern "C" fn PFBuildOptionsDestroy(options: PFBuildOptionsRef) { + drop(Box::from_raw(options)) +} + +/// Consumes the transform. +#[no_mangle] +pub unsafe extern "C" fn PFBuildOptionsSetTransform(options: PFBuildOptionsRef, + transform: PFRenderTransformRef) { + (*options).transform = *Box::from_raw(transform) +} + +#[no_mangle] +pub unsafe extern "C" fn PFBuildOptionsSetDilation(options: PFBuildOptionsRef, + dilation: *const PFVector2F) { + (*options).dilation = (*dilation).to_rust() +} + +#[no_mangle] +pub unsafe extern "C" fn PFBuildOptionsSetSubpixelAAEnabled(options: PFBuildOptionsRef, + subpixel_aa_enabled: bool) { + (*options).subpixel_aa_enabled = subpixel_aa_enabled +} + #[no_mangle] pub unsafe extern "C" fn PFSceneDestroy(scene: PFSceneRef) { drop(Box::from_raw(scene)) @@ -637,6 +722,40 @@ impl PFVector2I { } } +impl PFMatrix2x2F { + #[inline] + pub fn to_rust(&self) -> Matrix2x2F { + Matrix2x2F::row_major(self.m00, self.m01, self.m10, self.m11) + } +} + +impl PFTransform2DF { + #[inline] + pub fn to_rust(&self) -> Transform2DF { + Transform2DF { matrix: self.matrix.to_rust(), vector: self.vector.to_rust() } + } +} + +impl PFTransform3DF { + #[inline] + pub fn to_rust(&self) -> Transform3DF { + Transform3DF::row_major(self.m00, self.m01, self.m02, self.m03, + self.m10, self.m11, self.m12, self.m13, + self.m20, self.m21, self.m22, self.m23, + self.m30, self.m31, self.m32, self.m33) + } +} + +impl PFPerspective { + #[inline] + pub fn to_rust(&self) -> Perspective { + Perspective { + transform: self.transform.to_rust(), + window_size: self.window_size.to_rust(), + } + } +} + // Helpers for `renderer` impl PFRendererOptions { @@ -651,9 +770,3 @@ impl PFRendererOptions { } } } - -impl PFBuildOptions { - pub fn to_rust(&self) -> BuildOptions { - BuildOptions::default() - } -} diff --git a/examples/c_canvas_minimal/c_canvas_minimal.c b/examples/c_canvas_minimal/c_canvas_minimal.c index bcfa09b9..8feabc65 100644 --- a/examples/c_canvas_minimal/c_canvas_minimal.c +++ b/examples/c_canvas_minimal/c_canvas_minimal.c @@ -87,7 +87,7 @@ int main(int argc, const char **argv) { // Render the canvas to screen. PFSceneRef scene = PFCanvasCreateScene(canvas); PFSceneProxyRef scene_proxy = PFSceneProxyCreateFromSceneAndRayonExecutor(scene); - PFSceneProxyBuildAndRenderGL(scene_proxy, renderer, &(PFBuildOptions){0}); + PFSceneProxyBuildAndRenderGL(scene_proxy, renderer, PFBuildOptionsCreate()); SDL_GL_SwapWindow(window); // Wait for a keypress. diff --git a/geometry/src/transform2d.rs b/geometry/src/transform2d.rs index b48c8882..89d30aae 100644 --- a/geometry/src/transform2d.rs +++ b/geometry/src/transform2d.rs @@ -116,8 +116,8 @@ impl Sub for Matrix2x2F { #[derive(Clone, Copy, Debug, PartialEq)] pub struct Transform2DF { // Row-major order. - matrix: Matrix2x2F, - vector: Vector2F, + pub matrix: Matrix2x2F, + pub vector: Vector2F, } impl Default for Transform2DF {