parent
009f78ba26
commit
e04cc273ee
|
@ -5,6 +5,7 @@ target
|
||||||
/site/package-lock.json
|
/site/package-lock.json
|
||||||
/site/dist
|
/site/dist
|
||||||
node_modules
|
node_modules
|
||||||
|
/examples/c_canvas_minimal/build
|
||||||
|
|
||||||
# Editors
|
# Editors
|
||||||
*.swp
|
*.swp
|
||||||
|
|
|
@ -1184,6 +1184,19 @@ dependencies = [
|
||||||
"pathfinder_gpu 0.1.0",
|
"pathfinder_gpu 0.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pathfinder_c"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"pathfinder_canvas 0.1.0",
|
||||||
|
"pathfinder_geometry 0.3.0",
|
||||||
|
"pathfinder_gl 0.1.0",
|
||||||
|
"pathfinder_gpu 0.1.0",
|
||||||
|
"pathfinder_renderer 0.1.0",
|
||||||
|
"pathfinder_simd 0.3.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pathfinder_canvas"
|
name = "pathfinder_canvas"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
|
"c",
|
||||||
"canvas",
|
"canvas",
|
||||||
"demo/android/rust",
|
"demo/android/rust",
|
||||||
"demo/common",
|
"demo/common",
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
[package]
|
||||||
|
name = "pathfinder_c"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["staticlib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
gl = "0.6"
|
||||||
|
|
||||||
|
[dependencies.pathfinder_canvas]
|
||||||
|
path = "../canvas"
|
||||||
|
|
||||||
|
[dependencies.pathfinder_geometry]
|
||||||
|
path = "../geometry"
|
||||||
|
|
||||||
|
[dependencies.pathfinder_gl]
|
||||||
|
path = "../gl"
|
||||||
|
|
||||||
|
[dependencies.pathfinder_gpu]
|
||||||
|
path = "../gpu"
|
||||||
|
|
||||||
|
[dependencies.pathfinder_renderer]
|
||||||
|
path = "../renderer"
|
||||||
|
|
||||||
|
[dependencies.pathfinder_simd]
|
||||||
|
path = "../simd"
|
|
@ -0,0 +1,158 @@
|
||||||
|
// pathfinder/c/include/pathfinder/pathfinder.h
|
||||||
|
//
|
||||||
|
// Copyright © 2019 The Pathfinder Project Developers.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#ifndef PF_PATHFINDER_H
|
||||||
|
#define PF_PATHFINDER_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Macros
|
||||||
|
|
||||||
|
// `gl`
|
||||||
|
|
||||||
|
#define PF_GL_VERSION_GL3 0
|
||||||
|
#define PF_GL_VERSION_GLES3 1
|
||||||
|
|
||||||
|
// `gpu`
|
||||||
|
|
||||||
|
#define PF_CLEAR_FLAGS_HAS_COLOR 0x1
|
||||||
|
#define PF_CLEAR_FLAGS_HAS_DEPTH 0x2
|
||||||
|
#define PF_CLEAR_FLAGS_HAS_STENCIL 0x4
|
||||||
|
#define PF_CLEAR_FLAGS_HAS_RECT 0x8
|
||||||
|
|
||||||
|
// Types
|
||||||
|
|
||||||
|
// `canvas`
|
||||||
|
|
||||||
|
struct PFCanvas;
|
||||||
|
typedef struct PFCanvas *PFCanvasRef;
|
||||||
|
struct PFPath;
|
||||||
|
typedef struct PFPath *PFPathRef;
|
||||||
|
|
||||||
|
// `geometry`
|
||||||
|
|
||||||
|
struct PFColorF {
|
||||||
|
float r, g, b, a;
|
||||||
|
};
|
||||||
|
typedef struct PFColorF PFColorF;
|
||||||
|
struct PFPoint2DF {
|
||||||
|
float x, y;
|
||||||
|
};
|
||||||
|
typedef struct PFPoint2DF PFPoint2DF;
|
||||||
|
struct PFPoint2DI {
|
||||||
|
int32_t x, y;
|
||||||
|
};
|
||||||
|
typedef struct PFPoint2DI PFPoint2DI;
|
||||||
|
struct PFRectF {
|
||||||
|
PFPoint2DF origin, lower_right;
|
||||||
|
};
|
||||||
|
typedef struct PFRectF PFRectF;
|
||||||
|
struct PFRectI {
|
||||||
|
PFPoint2DI origin, lower_right;
|
||||||
|
};
|
||||||
|
typedef struct PFRectI PFRectI;
|
||||||
|
|
||||||
|
// `gl`
|
||||||
|
|
||||||
|
struct PFGLDevice;
|
||||||
|
typedef struct PFGLDevice *PFGLDeviceRef;
|
||||||
|
struct PFGLDestFramebuffer;
|
||||||
|
typedef struct PFGLDestFramebuffer *PFGLDestFramebufferRef;
|
||||||
|
typedef const void *(*PFGLFunctionLoader)(const char *data, void *userdata);
|
||||||
|
struct PFGLRenderer;
|
||||||
|
typedef struct PFGLRenderer *PFGLRendererRef;
|
||||||
|
typedef uint32_t PFGLVersion;
|
||||||
|
|
||||||
|
// `gpu`
|
||||||
|
|
||||||
|
typedef uint8_t PFClearFlags;
|
||||||
|
struct PFClearParams {
|
||||||
|
PFColorF color;
|
||||||
|
float depth;
|
||||||
|
uint8_t stencil;
|
||||||
|
PFRectI rect;
|
||||||
|
PFClearFlags flags;
|
||||||
|
};
|
||||||
|
typedef struct PFClearParams PFClearParams;
|
||||||
|
struct PFResourceLoader;
|
||||||
|
typedef struct PFResourceLoader *PFResourceLoaderRef;
|
||||||
|
|
||||||
|
// `renderer`
|
||||||
|
|
||||||
|
struct PFRenderOptions {
|
||||||
|
uint32_t placeholder;
|
||||||
|
};
|
||||||
|
typedef struct PFRenderOptions PFRenderOptions;
|
||||||
|
struct PFScene;
|
||||||
|
typedef struct PFScene *PFSceneRef;
|
||||||
|
struct PFSceneProxy;
|
||||||
|
typedef struct PFSceneProxy *PFSceneProxyRef;
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
|
||||||
|
// `canvas`
|
||||||
|
|
||||||
|
PFCanvasRef PFCanvasCreate(const PFPoint2DF *size);
|
||||||
|
void PFCanvasDestroy(PFCanvasRef canvas);
|
||||||
|
PFSceneRef PFCanvasCreateScene(PFCanvasRef canvas);
|
||||||
|
void PFCanvasFillRect(PFCanvasRef canvas, const PFRectF *rect);
|
||||||
|
void PFCanvasStrokeRect(PFCanvasRef canvas, const PFRectF *rect);
|
||||||
|
void PFCanvasSetLineWidth(PFCanvasRef canvas, float new_line_width);
|
||||||
|
void PFCanvasFillPath(PFCanvasRef canvas, PFPathRef path);
|
||||||
|
void PFCanvasStrokePath(PFCanvasRef canvas, PFPathRef path);
|
||||||
|
PFPathRef PFPathCreate();
|
||||||
|
void PFPathDestroy(PFPathRef path);
|
||||||
|
PFPathRef PFPathClone(PFPathRef path);
|
||||||
|
void PFPathMoveTo(PFPathRef path, const PFPoint2DF *to);
|
||||||
|
void PFPathLineTo(PFPathRef path, const PFPoint2DF *to);
|
||||||
|
void PFPathQuadraticCurveTo(PFPathRef path, const PFPoint2DF *ctrl, const PFPoint2DF *to);
|
||||||
|
void PFPathBezierCurveTo(PFPathRef path,
|
||||||
|
const PFPoint2DF *ctrl0,
|
||||||
|
const PFPoint2DF *ctrl1,
|
||||||
|
const PFPoint2DF *to);
|
||||||
|
void PFPathClosePath(PFPathRef path);
|
||||||
|
|
||||||
|
// `gl`
|
||||||
|
|
||||||
|
PFGLDestFramebufferRef PFGLDestFramebufferCreateFullWindow(const PFPoint2DI *window_size);
|
||||||
|
void PFGLDestFramebufferDestroy(PFGLDestFramebufferRef dest_framebuffer);
|
||||||
|
PFGLDeviceRef PFGLDeviceCreate(PFGLVersion version, uint32_t default_framebuffer);
|
||||||
|
void PFGLDeviceDestroy(PFGLDeviceRef device);
|
||||||
|
void PFGLDeviceClear(PFGLDeviceRef device, const PFClearParams *params);
|
||||||
|
void PFGLLoadWith(PFGLFunctionLoader loader, void *userdata);
|
||||||
|
PFGLRendererRef PFGLRendererCreate(PFGLDeviceRef device,
|
||||||
|
PFResourceLoaderRef resources,
|
||||||
|
PFGLDestFramebufferRef dest_framebuffer);
|
||||||
|
void PFGLRendererDestroy(PFGLRendererRef renderer);
|
||||||
|
/// Returns a borrowed reference to the device.
|
||||||
|
PFGLDeviceRef PFGLRendererGetDevice(PFGLRendererRef renderer);
|
||||||
|
void PFSceneProxyBuildAndRenderGL(PFSceneProxyRef scene_proxy,
|
||||||
|
PFGLRendererRef renderer,
|
||||||
|
const PFRenderOptions *options);
|
||||||
|
|
||||||
|
// `gpu`
|
||||||
|
|
||||||
|
PFResourceLoaderRef PFFilesystemResourceLoaderLocate();
|
||||||
|
void PFResourceLoaderDestroy(PFResourceLoaderRef loader);
|
||||||
|
|
||||||
|
// `renderer`
|
||||||
|
|
||||||
|
PFSceneProxyRef PFSceneProxyCreateFromSceneAndRayonExecutor(PFSceneRef scene);
|
||||||
|
void PFSceneProxyDestroy(PFSceneProxyRef scene_proxy);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,360 @@
|
||||||
|
// pathfinder/c/src/lib.rs
|
||||||
|
//
|
||||||
|
// Copyright © 2019 The Pathfinder Project Developers.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
//! C bindings to Pathfinder.
|
||||||
|
|
||||||
|
use gl;
|
||||||
|
use pathfinder_canvas::{CanvasRenderingContext2D, Path2D};
|
||||||
|
use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32};
|
||||||
|
use pathfinder_geometry::basic::rect::{RectF32, RectI32};
|
||||||
|
use pathfinder_geometry::color::ColorF;
|
||||||
|
use pathfinder_gl::{GLDevice, GLVersion};
|
||||||
|
use pathfinder_gpu::resources::{FilesystemResourceLoader, ResourceLoader};
|
||||||
|
use pathfinder_gpu::{ClearParams, Device};
|
||||||
|
use pathfinder_renderer::concurrent::rayon::RayonExecutor;
|
||||||
|
use pathfinder_renderer::concurrent::scene_proxy::SceneProxy;
|
||||||
|
use pathfinder_renderer::gpu::renderer::{DestFramebuffer, Renderer};
|
||||||
|
use pathfinder_renderer::options::RenderOptions;
|
||||||
|
use pathfinder_renderer::scene::Scene;
|
||||||
|
use pathfinder_simd::default::F32x4;
|
||||||
|
use std::ffi::CString;
|
||||||
|
use std::os::raw::{c_char, c_void};
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
|
||||||
|
pub const PF_CLEAR_FLAGS_HAS_COLOR: u8 = 0x1;
|
||||||
|
pub const PF_CLEAR_FLAGS_HAS_DEPTH: u8 = 0x2;
|
||||||
|
pub const PF_CLEAR_FLAGS_HAS_STENCIL: u8 = 0x4;
|
||||||
|
pub const PF_CLEAR_FLAGS_HAS_RECT: u8 = 0x8;
|
||||||
|
|
||||||
|
// Types
|
||||||
|
|
||||||
|
// `canvas`
|
||||||
|
pub type PFCanvasRef = *mut CanvasRenderingContext2D;
|
||||||
|
pub type PFPathRef = *mut Path2D;
|
||||||
|
|
||||||
|
// `geometry`
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct PFPoint2DF {
|
||||||
|
pub x: f32,
|
||||||
|
pub y: f32,
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct PFPoint2DI {
|
||||||
|
pub x: i32,
|
||||||
|
pub y: i32,
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct PFRectF {
|
||||||
|
pub origin: PFPoint2DF,
|
||||||
|
pub lower_right: PFPoint2DF,
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct PFRectI {
|
||||||
|
pub origin: PFPoint2DI,
|
||||||
|
pub lower_right: PFPoint2DI,
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct PFColorF {
|
||||||
|
pub r: f32,
|
||||||
|
pub g: f32,
|
||||||
|
pub b: f32,
|
||||||
|
pub a: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
// `gl`
|
||||||
|
pub type PFGLDeviceRef = *mut GLDevice;
|
||||||
|
pub type PFGLVersion = GLVersion;
|
||||||
|
pub type PFGLFunctionLoader = extern "C" fn(name: *const c_char, userdata: *mut c_void)
|
||||||
|
-> *const c_void;
|
||||||
|
// `gpu`
|
||||||
|
pub type PFGLDestFramebufferRef = *mut DestFramebuffer<GLDevice>;
|
||||||
|
pub type PFGLRendererRef = *mut Renderer<GLDevice>;
|
||||||
|
// FIXME(pcwalton): Double-boxing is unfortunate. Remove this when `std::raw::TraitObject` is
|
||||||
|
// stable?
|
||||||
|
pub type PFResourceLoaderRef = *mut Box<dyn ResourceLoader>;
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct PFClearParams {
|
||||||
|
pub color: PFColorF,
|
||||||
|
pub depth: f32,
|
||||||
|
pub stencil: u8,
|
||||||
|
pub rect: PFRectI,
|
||||||
|
pub flags: PFClearFlags,
|
||||||
|
}
|
||||||
|
pub type PFClearFlags = u8;
|
||||||
|
|
||||||
|
// `renderer`
|
||||||
|
pub type PFSceneRef = *mut Scene;
|
||||||
|
pub type PFSceneProxyRef = *mut SceneProxy;
|
||||||
|
// TODO(pcwalton)
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct PFRenderOptions {
|
||||||
|
pub placeholder: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
// `canvas`
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFCanvasCreate(size: *const PFPoint2DF) -> PFCanvasRef {
|
||||||
|
Box::into_raw(Box::new(CanvasRenderingContext2D::new((*size).to_rust())))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFCanvasDestroy(canvas: PFCanvasRef) {
|
||||||
|
drop(Box::from_raw(canvas))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consumes the canvas.
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFCanvasCreateScene(canvas: PFCanvasRef) -> PFSceneRef {
|
||||||
|
Box::into_raw(Box::new(Box::from_raw(canvas).into_scene()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFCanvasFillRect(canvas: PFCanvasRef, rect: *const PFRectF) {
|
||||||
|
(*canvas).fill_rect((*rect).to_rust())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFCanvasStrokeRect(canvas: PFCanvasRef, rect: *const PFRectF) {
|
||||||
|
(*canvas).stroke_rect((*rect).to_rust())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFCanvasSetLineWidth(canvas: PFCanvasRef, new_line_width: f32) {
|
||||||
|
(*canvas).set_line_width(new_line_width)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consumes the path.
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFCanvasFillPath(canvas: PFCanvasRef, path: PFPathRef) {
|
||||||
|
(*canvas).fill_path(*Box::from_raw(path))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consumes the path.
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFCanvasStrokePath(canvas: PFCanvasRef, path: PFPathRef) {
|
||||||
|
(*canvas).stroke_path(*Box::from_raw(path))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFPathCreate() -> PFPathRef {
|
||||||
|
Box::into_raw(Box::new(Path2D::new()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFPathDestroy(path: PFPathRef) {
|
||||||
|
drop(Box::from_raw(path))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFPathClone(path: PFPathRef) -> PFPathRef {
|
||||||
|
Box::into_raw(Box::new((*path).clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFPathMoveTo(path: PFPathRef, to: *const PFPoint2DF) {
|
||||||
|
(*path).move_to((*to).to_rust())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFPathLineTo(path: PFPathRef, to: *const PFPoint2DF) {
|
||||||
|
(*path).line_to((*to).to_rust())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFPathQuadraticCurveTo(path: PFPathRef,
|
||||||
|
ctrl: *const PFPoint2DF,
|
||||||
|
to: *const PFPoint2DF) {
|
||||||
|
(*path).quadratic_curve_to((*ctrl).to_rust(), (*to).to_rust())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFPathBezierCurveTo(path: PFPathRef,
|
||||||
|
ctrl0: *const PFPoint2DF,
|
||||||
|
ctrl1: *const PFPoint2DF,
|
||||||
|
to: *const PFPoint2DF) {
|
||||||
|
(*path).bezier_curve_to((*ctrl0).to_rust(), (*ctrl1).to_rust(), (*to).to_rust())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFPathClosePath(path: PFPathRef) {
|
||||||
|
(*path).close_path()
|
||||||
|
}
|
||||||
|
|
||||||
|
// `gl`
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFFilesystemResourceLoaderLocate() -> PFResourceLoaderRef {
|
||||||
|
let loader = Box::new(FilesystemResourceLoader::locate());
|
||||||
|
Box::into_raw(Box::new(loader as Box<dyn ResourceLoader>))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFGLLoadWith(loader: PFGLFunctionLoader, userdata: *mut c_void) {
|
||||||
|
gl::load_with(|name| {
|
||||||
|
let name = CString::new(name).unwrap();
|
||||||
|
loader(name.as_ptr(), userdata)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFGLDeviceCreate(version: PFGLVersion, default_framebuffer: u32)
|
||||||
|
-> PFGLDeviceRef {
|
||||||
|
Box::into_raw(Box::new(GLDevice::new(version, default_framebuffer)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFGLDeviceDestroy(device: PFGLDeviceRef) {
|
||||||
|
drop(Box::from_raw(device))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFGLDeviceClear(device: PFGLDeviceRef, params: *const PFClearParams) {
|
||||||
|
(*device).clear(&(*params).to_rust())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFResourceLoaderDestroy(loader: PFResourceLoaderRef) {
|
||||||
|
drop(Box::from_raw(loader))
|
||||||
|
}
|
||||||
|
|
||||||
|
// `gpu`
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFGLDestFramebufferCreateFullWindow(window_size: *const PFPoint2DI)
|
||||||
|
-> PFGLDestFramebufferRef {
|
||||||
|
Box::into_raw(Box::new(DestFramebuffer::full_window((*window_size).to_rust())))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFGLDestFramebufferDestroy(dest_framebuffer: PFGLDestFramebufferRef) {
|
||||||
|
drop(Box::from_raw(dest_framebuffer))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes ownership of `device` and `dest_framebuffer`, but not `resources`.
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFGLRendererCreate(device: PFGLDeviceRef,
|
||||||
|
resources: PFResourceLoaderRef,
|
||||||
|
dest_framebuffer: PFGLDestFramebufferRef)
|
||||||
|
-> PFGLRendererRef {
|
||||||
|
Box::into_raw(Box::new(Renderer::new(*Box::from_raw(device),
|
||||||
|
&**resources,
|
||||||
|
*Box::from_raw(dest_framebuffer))))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFGLRendererDestroy(renderer: PFGLRendererRef) {
|
||||||
|
drop(Box::from_raw(renderer))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFGLRendererGetDevice(renderer: PFGLRendererRef) -> PFGLDeviceRef {
|
||||||
|
&mut (*renderer).device
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFSceneProxyBuildAndRenderGL(scene_proxy: PFSceneProxyRef,
|
||||||
|
renderer: PFGLRendererRef,
|
||||||
|
options: *const PFRenderOptions) {
|
||||||
|
(*scene_proxy).build_and_render(&mut *renderer, (*options).to_rust())
|
||||||
|
}
|
||||||
|
|
||||||
|
// `renderer`
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFSceneDestroy(scene: PFSceneRef) {
|
||||||
|
drop(Box::from_raw(scene))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFSceneProxyCreateFromSceneAndRayonExecutor(scene: PFSceneRef)
|
||||||
|
-> PFSceneProxyRef {
|
||||||
|
Box::into_raw(Box::new(SceneProxy::from_scene(*Box::from_raw(scene), RayonExecutor)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn PFSceneProxyDestroy(scene_proxy: PFSceneProxyRef) {
|
||||||
|
drop(Box::from_raw(scene_proxy))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helpers for `geometry`
|
||||||
|
|
||||||
|
impl PFColorF {
|
||||||
|
#[inline]
|
||||||
|
pub fn to_rust(&self) -> ColorF {
|
||||||
|
ColorF(F32x4::new(self.r, self.g, self.b, self.a))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PFRectF {
|
||||||
|
#[inline]
|
||||||
|
pub fn to_rust(&self) -> RectF32 {
|
||||||
|
RectF32::from_points(self.origin.to_rust(), self.lower_right.to_rust())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PFRectI {
|
||||||
|
#[inline]
|
||||||
|
pub fn to_rust(&self) -> RectI32 {
|
||||||
|
RectI32::from_points(self.origin.to_rust(), self.lower_right.to_rust())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PFPoint2DF {
|
||||||
|
#[inline]
|
||||||
|
pub fn to_rust(&self) -> Point2DF32 {
|
||||||
|
Point2DF32::new(self.x, self.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PFPoint2DI {
|
||||||
|
#[inline]
|
||||||
|
pub fn to_rust(&self) -> Point2DI32 {
|
||||||
|
Point2DI32::new(self.x, self.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helpers for `gpu`
|
||||||
|
|
||||||
|
impl PFClearParams {
|
||||||
|
pub fn to_rust(&self) -> ClearParams {
|
||||||
|
ClearParams {
|
||||||
|
color: if (self.flags & PF_CLEAR_FLAGS_HAS_COLOR) != 0 {
|
||||||
|
Some(self.color.to_rust())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
rect: if (self.flags & PF_CLEAR_FLAGS_HAS_RECT) != 0 {
|
||||||
|
Some(self.rect.to_rust())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
depth: if (self.flags & PF_CLEAR_FLAGS_HAS_DEPTH) != 0 {
|
||||||
|
Some(self.depth)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
stencil: if (self.flags & PF_CLEAR_FLAGS_HAS_STENCIL) != 0 {
|
||||||
|
Some(self.stencil)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helpers for `renderer`
|
||||||
|
|
||||||
|
impl PFRenderOptions {
|
||||||
|
pub fn to_rust(&self) -> RenderOptions {
|
||||||
|
RenderOptions::default()
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,9 @@ version = "0.1.0"
|
||||||
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
|
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["rlib", "staticlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
font-kit = "0.1"
|
font-kit = "0.1"
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
OBJ_DIR?=build
|
||||||
|
TARGET_DIR?=build
|
||||||
|
SRC_DIR?=.
|
||||||
|
RUST_TARGET_DIR?=../../target
|
||||||
|
RUST_SRC_DIR?=../../c
|
||||||
|
RUSTFLAGS?=-C target-cpu=native
|
||||||
|
|
||||||
|
CFLAGS?=-Wall -g -I../../c/include
|
||||||
|
LIBS?=-lpathfinder_c
|
||||||
|
MKDIR?=mkdir -p
|
||||||
|
RM?=rm
|
||||||
|
CARGO?=cargo
|
||||||
|
|
||||||
|
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
|
||||||
|
else
|
||||||
|
LIBS+=-lGL
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(DEBUG),)
|
||||||
|
CFLAGS+=-O2
|
||||||
|
LDFLAGS?=-L$(RUST_TARGET_DIR)/release
|
||||||
|
CARGOFLAGS?=--release
|
||||||
|
else
|
||||||
|
CFLAGS+=-O0
|
||||||
|
LDFLAGS?=-L$(RUST_TARGET_DIR)/debug
|
||||||
|
CARGOFLAGS?=
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: $(TARGET_DIR)/c_canvas_minimal
|
||||||
|
|
||||||
|
.PHONY: clean rustlib
|
||||||
|
|
||||||
|
$(TARGET_DIR)/c_canvas_minimal: $(OBJ_DIR)/c_canvas_minimal.o rustlib
|
||||||
|
$(MKDIR) $(TARGET_DIR) && $(CC) $(LDFLAGS) $(LIBS) `sdl2-config --libs` -o $@ $<
|
||||||
|
|
||||||
|
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
|
||||||
|
$(MKDIR) $(OBJ_DIR) && $(CC) -c $(CFLAGS) `sdl2-config --cflags` -o $@ $<
|
||||||
|
|
||||||
|
rustlib:
|
||||||
|
cd $(RUST_SRC_DIR) && RUSTFLAGS="$(RUSTFLAGS)" $(CARGO) build $(CARGOFLAGS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) -rf $(TARGET_DIR) && $(RM) -rf $(OBJ_DIR)
|
|
@ -0,0 +1,117 @@
|
||||||
|
// pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c
|
||||||
|
//
|
||||||
|
// Copyright © 2019 The Pathfinder Project Developers.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_opengl.h>
|
||||||
|
#include <pathfinder/pathfinder.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static const void *LoadGLFunction(const char *name, void *userdata);
|
||||||
|
static void SDLFailed(const char *msg);
|
||||||
|
|
||||||
|
int main(int argc, const char **argv) {
|
||||||
|
// Set up SDL2.
|
||||||
|
if (SDL_Init(SDL_INIT_EVENTS | SDL_INIT_VIDEO) != 0)
|
||||||
|
SDLFailed("Failed to initialize SDL");
|
||||||
|
|
||||||
|
// Make sure we have at least a GL 3.0 context. Pathfinder requires this.
|
||||||
|
if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3) != 0)
|
||||||
|
SDLFailed("Failed to set GL major version");
|
||||||
|
if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2) != 0)
|
||||||
|
SDLFailed("Failed to set GL minor version");
|
||||||
|
if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE) != 0)
|
||||||
|
SDLFailed("Failed to set GL profile");
|
||||||
|
if (SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1) != 0)
|
||||||
|
SDLFailed("Failed to make GL context double-buffered");
|
||||||
|
|
||||||
|
// Open a window.
|
||||||
|
SDL_Window *window = SDL_CreateWindow("Minimal canvas example (C API)",
|
||||||
|
SDL_WINDOWPOS_CENTERED,
|
||||||
|
SDL_WINDOWPOS_CENTERED,
|
||||||
|
640,
|
||||||
|
480,
|
||||||
|
SDL_WINDOW_OPENGL);
|
||||||
|
if (window == NULL)
|
||||||
|
SDLFailed("Failed to create SDL window");
|
||||||
|
|
||||||
|
// Create the GL context, and make it current.
|
||||||
|
SDL_GLContext gl_context = SDL_GL_CreateContext(window);
|
||||||
|
if (gl_context == NULL)
|
||||||
|
SDLFailed("Failed to create GL context");
|
||||||
|
|
||||||
|
// Put the window on screen.
|
||||||
|
SDL_ShowWindow(window);
|
||||||
|
|
||||||
|
// Create a Pathfinder renderer.
|
||||||
|
PFGLLoadWith(LoadGLFunction, NULL);
|
||||||
|
PFGLDestFramebufferRef dest_framebuffer =
|
||||||
|
PFGLDestFramebufferCreateFullWindow(&(PFPoint2DI){640, 480});
|
||||||
|
PFGLRendererRef renderer = PFGLRendererCreate(PFGLDeviceCreate(PF_GL_VERSION_GL3, 0),
|
||||||
|
PFFilesystemResourceLoaderLocate(),
|
||||||
|
dest_framebuffer);
|
||||||
|
|
||||||
|
// Clear to white.
|
||||||
|
PFGLDeviceClear(PFGLRendererGetDevice(renderer), &(PFClearParams){
|
||||||
|
(PFColorF){1.0, 1.0, 1.0, 1.0}, 0.0, 0, {0}, PF_CLEAR_FLAGS_HAS_COLOR
|
||||||
|
});
|
||||||
|
|
||||||
|
// Make a canvas. We're going to draw a house.
|
||||||
|
PFCanvasRef canvas = PFCanvasCreate(&(PFPoint2DF){640.0f, 480.0f});
|
||||||
|
|
||||||
|
// Set line width.
|
||||||
|
PFCanvasSetLineWidth(canvas, 10.0f);
|
||||||
|
|
||||||
|
// Draw walls.
|
||||||
|
PFCanvasStrokeRect(canvas, &(PFRectF){{75.0f, 140.0f}, {225.0f, 250.0f}});
|
||||||
|
|
||||||
|
// Draw door.
|
||||||
|
PFCanvasFillRect(canvas, &(PFRectF){{130.0f, 190.0f}, {170.0f, 250.0f}});
|
||||||
|
|
||||||
|
// Draw roof.
|
||||||
|
PFPathRef path = PFPathCreate();
|
||||||
|
PFPathMoveTo(path, &(PFPoint2DF){50.0, 140.0});
|
||||||
|
PFPathLineTo(path, &(PFPoint2DF){150.0, 60.0});
|
||||||
|
PFPathLineTo(path, &(PFPoint2DF){250.0, 140.0});
|
||||||
|
PFPathClosePath(path);
|
||||||
|
PFCanvasStrokePath(canvas, path);
|
||||||
|
|
||||||
|
// Render the canvas to screen.
|
||||||
|
PFSceneRef scene = PFCanvasCreateScene(canvas);
|
||||||
|
PFSceneProxyRef scene_proxy = PFSceneProxyCreateFromSceneAndRayonExecutor(scene);
|
||||||
|
PFSceneProxyBuildAndRenderGL(scene_proxy, renderer, &(PFRenderOptions){0});
|
||||||
|
SDL_GL_SwapWindow(window);
|
||||||
|
|
||||||
|
// Wait for a keypress.
|
||||||
|
while (true) {
|
||||||
|
SDL_Event event;
|
||||||
|
if (SDL_WaitEvent(&event) == 0)
|
||||||
|
SDLFailed("Failed to get SDL event");
|
||||||
|
if (event.type == SDL_QUIT ||
|
||||||
|
(event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finish up.
|
||||||
|
SDL_Quit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const void *LoadGLFunction(const char *name, void *userdata) {
|
||||||
|
return SDL_GL_GetProcAddress(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SDLFailed(const char *msg) {
|
||||||
|
fprintf(stderr, "%s: %s\n", msg, SDL_GetError());
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
|
@ -4,6 +4,9 @@ version = "0.1.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
|
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["rlib", "staticlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
gl = "0.6"
|
gl = "0.6"
|
||||||
rustache = "0.1"
|
rustache = "0.1"
|
||||||
|
|
|
@ -859,11 +859,13 @@ impl VertexAttrTypeExt for VertexAttrType {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The version/dialect of OpenGL we should render with.
|
/// The version/dialect of OpenGL we should render with.
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
#[repr(u32)]
|
||||||
pub enum GLVersion {
|
pub enum GLVersion {
|
||||||
/// OpenGL 3.0+, core profile.
|
/// OpenGL 3.0+, core profile.
|
||||||
GL3,
|
GL3 = 0,
|
||||||
/// OpenGL ES 3.0+.
|
/// OpenGL ES 3.0+.
|
||||||
GLES3,
|
GLES3 = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GLVersion {
|
impl GLVersion {
|
||||||
|
|
Loading…
Reference in New Issue