Add transform support to the C API, and fix build problems

This commit is contained in:
Patrick Walton 2019-06-24 14:03:26 -07:00
parent 82171088c5
commit a8d20cb37f
4 changed files with 148 additions and 25 deletions

View File

@ -2,18 +2,28 @@ language = "C"
header = """\ header = """\
/* Generated code. Do not edit; instead run `cargo build` in `pathfinder_c`. */ /* Generated code. Do not edit; instead run `cargo build` in `pathfinder_c`. */
#ifdef __cplusplus
extern \"C\" { extern \"C\" {
#endif
"""
trailer = """\
#ifdef __cplusplus
}
#endif
""" """
trailer = "}"
include_guard = "PF_PATHFINDER_H" include_guard = "PF_PATHFINDER_H"
include_version = true include_version = true
[parse] [parse]
parse_deps = true parse_deps = true
include = [ include = [
"font-kit",
"metal",
"pathfinder_canvas", "pathfinder_canvas",
"pathfinder_content", "pathfinder_content",
"pathfinder_geometry", "pathfinder_geometry",
"pathfinder_gl", "pathfinder_gl",
"pathfinder_gpu",
"pathfinder_metal",
"pathfinder_renderer", "pathfinder_renderer",
] ]

View File

@ -19,6 +19,8 @@ use pathfinder_content::color::{ColorF, ColorU};
use pathfinder_content::outline::ArcDirection; use pathfinder_content::outline::ArcDirection;
use pathfinder_content::stroke::LineCap; use pathfinder_content::stroke::LineCap;
use pathfinder_geometry::rect::{RectF, RectI}; 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_geometry::vector::{Vector2F, Vector2I};
use pathfinder_gl::{GLDevice, GLVersion}; use pathfinder_gl::{GLDevice, GLVersion};
use pathfinder_gpu::resources::{FilesystemResourceLoader, ResourceLoader}; 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::concurrent::scene_proxy::SceneProxy;
use pathfinder_renderer::gpu::options::{DestFramebuffer, RendererOptions}; use pathfinder_renderer::gpu::options::{DestFramebuffer, RendererOptions};
use pathfinder_renderer::gpu::renderer::Renderer; use pathfinder_renderer::gpu::renderer::Renderer;
use pathfinder_renderer::options::BuildOptions; use pathfinder_renderer::options::{BuildOptions, RenderTransform};
use pathfinder_renderer::scene::Scene; use pathfinder_renderer::scene::Scene;
use pathfinder_simd::default::F32x4; use pathfinder_simd::default::F32x4;
use std::ffi::CString; 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_CW: u8 = 0;
pub const PF_ARC_DIRECTION_CCW: u8 = 1; 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` // `renderer`
pub const PF_RENDERER_OPTIONS_FLAGS_HAS_BACKGROUND_COLOR: u8 = 0x1; pub const PF_RENDERER_OPTIONS_FLAGS_HAS_BACKGROUND_COLOR: u8 = 0x1;
@ -120,10 +127,35 @@ pub struct PFRectI {
pub origin: PFVector2I, pub origin: PFVector2I,
pub lower_right: 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` // `gl`
pub type PFGLDeviceRef = *mut GLDevice; 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) pub type PFGLFunctionLoader = extern "C" fn(name: *const c_char, userdata: *mut c_void)
-> *const c_void; -> *const c_void;
// `gpu` // `gpu`
@ -135,7 +167,8 @@ pub type PFMetalDestFramebufferRef = *mut DestFramebuffer<MetalDevice>;
pub type PFMetalRendererRef = *mut Renderer<MetalDevice>; pub type PFMetalRendererRef = *mut Renderer<MetalDevice>;
// FIXME(pcwalton): Double-boxing is unfortunate. Remove this when `std::raw::TraitObject` is // FIXME(pcwalton): Double-boxing is unfortunate. Remove this when `std::raw::TraitObject` is
// stable? // stable?
pub type PFResourceLoaderRef = *mut Box<dyn ResourceLoader>; pub type PFResourceLoaderRef = *mut ResourceLoaderWrapper;
pub struct ResourceLoaderWrapper(Box<dyn ResourceLoader>);
// `metal` // `metal`
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] #[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
@ -150,11 +183,8 @@ pub struct PFRendererOptions {
pub flags: PFRendererOptionsFlags, pub flags: PFRendererOptionsFlags,
} }
pub type PFRendererOptionsFlags = u8; pub type PFRendererOptionsFlags = u8;
// TODO(pcwalton) pub type PFBuildOptionsRef = *mut BuildOptions;
#[repr(C)] pub type PFRenderTransformRef = *mut RenderTransform;
pub struct PFBuildOptions {
pub placeholder: u32,
}
// `canvas` // `canvas`
@ -421,7 +451,7 @@ pub unsafe extern "C" fn PFFillStyleDestroy(fill_style: PFFillStyleRef) {
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn PFFilesystemResourceLoaderLocate() -> PFResourceLoaderRef { pub unsafe extern "C" fn PFFilesystemResourceLoaderLocate() -> PFResourceLoaderRef {
let loader = Box::new(FilesystemResourceLoader::locate()); let loader = Box::new(FilesystemResourceLoader::locate());
Box::into_raw(Box::new(loader as Box<dyn ResourceLoader>)) Box::into_raw(Box::new(ResourceLoaderWrapper(loader as Box<dyn ResourceLoader>)))
} }
#[no_mangle] #[no_mangle]
@ -435,6 +465,7 @@ pub unsafe extern "C" fn PFGLLoadWith(loader: PFGLFunctionLoader, userdata: *mut
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn PFGLDeviceCreate(version: PFGLVersion, default_framebuffer: u32) pub unsafe extern "C" fn PFGLDeviceCreate(version: PFGLVersion, default_framebuffer: u32)
-> PFGLDeviceRef { -> PFGLDeviceRef {
let version = match version { PF_GL_VERSION_GLES3 => GLVersion::GLES3, _ => GLVersion::GL3 };
Box::into_raw(Box::new(GLDevice::new(version, default_framebuffer))) 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) options: *const PFRendererOptions)
-> PFGLRendererRef { -> PFGLRendererRef {
Box::into_raw(Box::new(Renderer::new(*Box::from_raw(device), Box::into_raw(Box::new(Renderer::new(*Box::from_raw(device),
&**resources, &*((*resources).0),
*Box::from_raw(dest_framebuffer), *Box::from_raw(dest_framebuffer),
(*options).to_rust()))) (*options).to_rust())))
} }
@ -507,7 +538,7 @@ pub unsafe extern "C" fn PFMetalRendererCreate(device: PFMetalDeviceRef,
options: *const PFRendererOptions) options: *const PFRendererOptions)
-> PFMetalRendererRef { -> PFMetalRendererRef {
Box::into_raw(Box::new(Renderer::new(*Box::from_raw(device), Box::into_raw(Box::new(Renderer::new(*Box::from_raw(device),
&**resources, &*((*resources).0),
*Box::from_raw(dest_framebuffer), *Box::from_raw(dest_framebuffer),
(*options).to_rust()))) (*options).to_rust())))
} }
@ -524,19 +555,21 @@ pub unsafe extern "C" fn PFMetalRendererGetDevice(renderer: PFMetalRendererRef)
&mut (*renderer).device &mut (*renderer).device
} }
// Consumes `build_options`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn PFSceneProxyBuildAndRenderGL(scene_proxy: PFSceneProxyRef, pub unsafe extern "C" fn PFSceneProxyBuildAndRenderGL(scene_proxy: PFSceneProxyRef,
renderer: PFGLRendererRef, renderer: PFGLRendererRef,
build_options: *const PFBuildOptions) { build_options: PFBuildOptionsRef) {
(*scene_proxy).build_and_render(&mut *renderer, (*build_options).to_rust()) (*scene_proxy).build_and_render(&mut *renderer, *Box::from_raw(build_options))
} }
// Consumes `build_options`.
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] #[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn PFSceneProxyBuildAndRenderMetal(scene_proxy: PFSceneProxyRef, pub unsafe extern "C" fn PFSceneProxyBuildAndRenderMetal(scene_proxy: PFSceneProxyRef,
renderer: PFMetalRendererRef, renderer: PFMetalRendererRef,
build_options: *const PFBuildOptions) { build_options: PFBuildOptionsRef) {
(*scene_proxy).build_and_render(&mut *renderer, (*build_options).to_rust()) (*scene_proxy).build_and_render(&mut *renderer, *Box::from_raw(build_options))
} }
// `metal` // `metal`
@ -554,8 +587,60 @@ pub unsafe extern "C" fn PFMetalDeviceDestroy(device: PFMetalDeviceRef) {
drop(Box::from_raw(device)) 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` // `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] #[no_mangle]
pub unsafe extern "C" fn PFSceneDestroy(scene: PFSceneRef) { pub unsafe extern "C" fn PFSceneDestroy(scene: PFSceneRef) {
drop(Box::from_raw(scene)) 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` // Helpers for `renderer`
impl PFRendererOptions { impl PFRendererOptions {
@ -651,9 +770,3 @@ impl PFRendererOptions {
} }
} }
} }
impl PFBuildOptions {
pub fn to_rust(&self) -> BuildOptions {
BuildOptions::default()
}
}

View File

@ -87,7 +87,7 @@ int main(int argc, const char **argv) {
// Render the canvas to screen. // Render the canvas to screen.
PFSceneRef scene = PFCanvasCreateScene(canvas); PFSceneRef scene = PFCanvasCreateScene(canvas);
PFSceneProxyRef scene_proxy = PFSceneProxyCreateFromSceneAndRayonExecutor(scene); PFSceneProxyRef scene_proxy = PFSceneProxyCreateFromSceneAndRayonExecutor(scene);
PFSceneProxyBuildAndRenderGL(scene_proxy, renderer, &(PFBuildOptions){0}); PFSceneProxyBuildAndRenderGL(scene_proxy, renderer, PFBuildOptionsCreate());
SDL_GL_SwapWindow(window); SDL_GL_SwapWindow(window);
// Wait for a keypress. // Wait for a keypress.

View File

@ -116,8 +116,8 @@ impl Sub<Matrix2x2F> for Matrix2x2F {
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
pub struct Transform2DF { pub struct Transform2DF {
// Row-major order. // Row-major order.
matrix: Matrix2x2F, pub matrix: Matrix2x2F,
vector: Vector2F, pub vector: Vector2F,
} }
impl Default for Transform2DF { impl Default for Transform2DF {