Try to optimize
This commit is contained in:
parent
5fa9e8f883
commit
ca750dda7b
19
c/Cargo.toml
19
c/Cargo.toml
|
@ -4,6 +4,9 @@ version = "0.1.0"
|
||||||
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
|
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
metal = ["dep:core-foundation", "dep:io-surface", "dep:metal", "dep:pathfinder_metal"]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["staticlib", "cdylib"]
|
crate-type = ["staticlib", "cdylib"]
|
||||||
name = "pathfinder"
|
name = "pathfinder"
|
||||||
|
@ -51,10 +54,18 @@ path = "../simd"
|
||||||
[dependencies.pathfinder_svg]
|
[dependencies.pathfinder_svg]
|
||||||
path = "../svg"
|
path = "../svg"
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies.core-foundation]
|
||||||
core-foundation = "0.6"
|
version = "0.6"
|
||||||
io-surface = "0.12"
|
optional = true
|
||||||
metal = "0.18"
|
|
||||||
|
[target.'cfg(target_os = "macos")'.dependencies.io-surface]
|
||||||
|
version = "0.12"
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "macos")'.dependencies.metal]
|
||||||
|
version = "0.18"
|
||||||
|
optional = true
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies.pathfinder_metal]
|
[target.'cfg(target_os = "macos")'.dependencies.pathfinder_metal]
|
||||||
path = "../metal"
|
path = "../metal"
|
||||||
|
optional = true
|
||||||
|
|
824
c/src/lib.rs
824
c/src/lib.rs
File diff suppressed because it is too large
Load Diff
|
@ -78,10 +78,8 @@ pub struct Canvas {
|
||||||
|
|
||||||
impl Canvas {
|
impl Canvas {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(size: Vector2F) -> Canvas {
|
pub fn new() -> Canvas {
|
||||||
let mut scene = Scene::new();
|
Canvas::from_scene(Scene::new())
|
||||||
scene.set_view_box(RectF::new(Vector2F::zero(), size));
|
|
||||||
Canvas::from_scene(scene)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -130,10 +128,10 @@ impl Canvas {
|
||||||
self.scene.view_box().size().ceil().to_i32()
|
self.scene.view_box().size().ceil().to_i32()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_size(&mut self, new_size: Vector2I) {
|
/// This resets the canvas' bounds. Do not call this mid-draw.
|
||||||
let new_view_box = RectI::new(Vector2I::default(), new_size).to_f32();
|
pub fn set_size(&mut self, new_size: Vector2F) {
|
||||||
self.scene.set_bounds(new_view_box);
|
self.scene.set_bounds(RectF::default());
|
||||||
self.scene.set_view_box(new_view_box);
|
self.scene.set_view_box(RectF::new(Vector2F::zero(), new_size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
use crate::{CanvasRenderingContext2D, State, TextAlign, TextBaseline};
|
use crate::{CanvasRenderingContext2D, State, TextAlign, TextBaseline};
|
||||||
use font_kit::canvas::RasterizationOptions;
|
use font_kit::canvas::RasterizationOptions;
|
||||||
use font_kit::error::{FontLoadingError, SelectionError};
|
use font_kit::error::{GlyphLoadingError, FontLoadingError, SelectionError};
|
||||||
use font_kit::family_name::FamilyName;
|
use font_kit::family_name::FamilyName;
|
||||||
use font_kit::handle::Handle;
|
use font_kit::handle::Handle;
|
||||||
use font_kit::hinting::HintingOptions;
|
use font_kit::hinting::HintingOptions;
|
||||||
|
@ -36,10 +36,10 @@ impl CanvasRenderingContext2D {
|
||||||
/// fill the text that you passed into `measure_text()` with the layout-related style
|
/// fill the text that you passed into `measure_text()` with the layout-related style
|
||||||
/// properties set at the time you called that function. This allows Pathfinder to skip having
|
/// properties set at the time you called that function. This allows Pathfinder to skip having
|
||||||
/// to lay out the text again.
|
/// to lay out the text again.
|
||||||
pub fn fill_text<T>(&mut self, text: &T, position: Vector2F) where T: ToTextLayout + ?Sized {
|
pub fn fill_text<T>(&mut self, text: &T, position: Vector2F) -> Result<(), GlyphLoadingError> where T: ToTextLayout + ?Sized {
|
||||||
let paint = self.current_state.resolve_paint(&self.current_state.fill_paint);
|
let paint = self.current_state.resolve_paint(&self.current_state.fill_paint);
|
||||||
let paint_id = self.canvas.scene.push_paint(&paint);
|
let paint_id = self.canvas.scene.push_paint(&paint);
|
||||||
self.fill_or_stroke_text(text, position, paint_id, TextRenderMode::Fill);
|
self.fill_or_stroke_text(text, position, paint_id, TextRenderMode::Fill)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Strokes the given text using the current style.
|
/// Strokes the given text using the current style.
|
||||||
|
@ -48,11 +48,11 @@ impl CanvasRenderingContext2D {
|
||||||
/// stroke the text that you passed into `measure_text()` with the layout-related style
|
/// stroke the text that you passed into `measure_text()` with the layout-related style
|
||||||
/// properties set at the time you called that function. This allows Pathfinder to skip having
|
/// properties set at the time you called that function. This allows Pathfinder to skip having
|
||||||
/// to lay out the text again.
|
/// to lay out the text again.
|
||||||
pub fn stroke_text<T>(&mut self, text: &T, position: Vector2F) where T: ToTextLayout + ?Sized {
|
pub fn stroke_text<T>(&mut self, text: &T, position: Vector2F) -> Result<(), GlyphLoadingError> where T: ToTextLayout + ?Sized {
|
||||||
let paint = self.current_state.resolve_paint(&self.current_state.stroke_paint);
|
let paint = self.current_state.resolve_paint(&self.current_state.stroke_paint);
|
||||||
let paint_id = self.canvas.scene.push_paint(&paint);
|
let paint_id = self.canvas.scene.push_paint(&paint);
|
||||||
let render_mode = TextRenderMode::Stroke(self.current_state.resolve_stroke_style());
|
let render_mode = TextRenderMode::Stroke(self.current_state.resolve_stroke_style());
|
||||||
self.fill_or_stroke_text(text, position, paint_id, render_mode);
|
self.fill_or_stroke_text(text, position, paint_id, render_mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns metrics of the given text using the current style.
|
/// Returns metrics of the given text using the current style.
|
||||||
|
@ -68,7 +68,7 @@ impl CanvasRenderingContext2D {
|
||||||
text: &T,
|
text: &T,
|
||||||
mut position: Vector2F,
|
mut position: Vector2F,
|
||||||
paint_id: PaintId,
|
paint_id: PaintId,
|
||||||
render_mode: TextRenderMode)
|
render_mode: TextRenderMode) -> Result<(), GlyphLoadingError>
|
||||||
where T: ToTextLayout + ?Sized {
|
where T: ToTextLayout + ?Sized {
|
||||||
let layout = text.layout(CanvasState(&self.current_state));
|
let layout = text.layout(CanvasState(&self.current_state));
|
||||||
|
|
||||||
|
@ -78,8 +78,7 @@ impl CanvasRenderingContext2D {
|
||||||
position += layout.text_origin();
|
position += layout.text_origin();
|
||||||
let transform = self.current_state.transform * Transform2F::from_translation(position);
|
let transform = self.current_state.transform * Transform2F::from_translation(position);
|
||||||
|
|
||||||
// TODO(pcwalton): Report errors.
|
self.canvas_font_context
|
||||||
drop(self.canvas_font_context
|
|
||||||
.0
|
.0
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.font_context
|
.font_context
|
||||||
|
@ -93,7 +92,9 @@ impl CanvasRenderingContext2D {
|
||||||
clip_path,
|
clip_path,
|
||||||
blend_mode,
|
blend_mode,
|
||||||
paint_id,
|
paint_id,
|
||||||
}));
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Text styles
|
// Text styles
|
||||||
|
|
|
@ -12,7 +12,7 @@ egl = "0.2"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
smallvec = "1.2"
|
smallvec = "1.2"
|
||||||
glutin = { version = "0.23", optional = true }
|
glutin = { version = "0.23", optional = true }
|
||||||
crossbeam-channel = "0.4"
|
flume = { version = "0.11", default-features = false, features = ["eventual-fairness"] }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
|
@ -66,8 +66,8 @@ mod magicleap;
|
||||||
mod mocked_c_api;
|
mod mocked_c_api;
|
||||||
|
|
||||||
struct ImmersiveApp {
|
struct ImmersiveApp {
|
||||||
sender: crossbeam_channel::Sender<Event>,
|
sender: flume::Sender<Event>,
|
||||||
receiver: crossbeam_channel::Receiver<Event>,
|
receiver: flume::Receiver<Event>,
|
||||||
demo: DemoApp<MagicLeapWindow>,
|
demo: DemoApp<MagicLeapWindow>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ pub extern "C" fn magicleap_pathfinder_demo_init(egl_display: EGLDisplay, egl_co
|
||||||
let demo = DemoApp::new(window, window_size, options);
|
let demo = DemoApp::new(window, window_size, options);
|
||||||
info!("Initialized app");
|
info!("Initialized app");
|
||||||
|
|
||||||
let (sender, receiver) = crossbeam_channel::unbounded();
|
let (sender, receiver) = flume::unbounded();
|
||||||
Box::into_raw(Box::new(ImmersiveApp { sender, receiver, demo })) as *mut c_void
|
Box::into_raw(Box::new(ImmersiveApp { sender, receiver, demo })) as *mut c_void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -785,7 +785,7 @@ impl Device for GLDevice {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end_commands(&self) {
|
fn end_commands(&self) {
|
||||||
unsafe { gl::Flush(); }
|
//unsafe { gl::Flush(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_arrays(&self, index_count: u32, render_state: &RenderState<Self>) {
|
fn draw_arrays(&self, index_count: u32, render_state: &RenderState<Self>) {
|
||||||
|
|
|
@ -12,7 +12,7 @@ homepage = "https://github.com/servo/pathfinder"
|
||||||
bitflags = "1.0"
|
bitflags = "1.0"
|
||||||
byte-slice-cast = "0.3"
|
byte-slice-cast = "0.3"
|
||||||
byteorder = "1.2"
|
byteorder = "1.2"
|
||||||
crossbeam-channel = "0.4"
|
flume = { version = "0.11", default-features = false, features = ["eventual-fairness"] }
|
||||||
fxhash = "0.2"
|
fxhash = "0.2"
|
||||||
half = "1.5"
|
half = "1.5"
|
||||||
hashbrown = "0.7"
|
hashbrown = "0.7"
|
||||||
|
|
|
@ -25,7 +25,7 @@ use crate::gpu::renderer::Renderer;
|
||||||
use crate::gpu_data::RenderCommand;
|
use crate::gpu_data::RenderCommand;
|
||||||
use crate::options::{BuildOptions, RenderCommandListener};
|
use crate::options::{BuildOptions, RenderCommandListener};
|
||||||
use crate::scene::{Scene, SceneSink};
|
use crate::scene::{Scene, SceneSink};
|
||||||
use crossbeam_channel::{self, Receiver, Sender};
|
use flume::{self, Receiver, Sender};
|
||||||
use pathfinder_geometry::rect::RectF;
|
use pathfinder_geometry::rect::RectF;
|
||||||
use pathfinder_gpu::Device;
|
use pathfinder_gpu::Device;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
@ -60,9 +60,9 @@ impl SceneProxy {
|
||||||
-> SceneProxy
|
-> SceneProxy
|
||||||
where E: Executor + Send + 'static {
|
where E: Executor + Send + 'static {
|
||||||
let (main_to_worker_sender, main_to_worker_receiver) =
|
let (main_to_worker_sender, main_to_worker_receiver) =
|
||||||
crossbeam_channel::bounded(MAX_MESSAGES_IN_FLIGHT);
|
flume::bounded(MAX_MESSAGES_IN_FLIGHT);
|
||||||
let (worker_to_main_sender, worker_to_main_receiver) =
|
let (worker_to_main_sender, worker_to_main_receiver) =
|
||||||
crossbeam_channel::bounded(MAX_MESSAGES_IN_FLIGHT);
|
flume::bounded(MAX_MESSAGES_IN_FLIGHT);
|
||||||
let listener = RenderCommandListener::new(Box::new(move |command| {
|
let listener = RenderCommandListener::new(Box::new(move |command| {
|
||||||
drop(worker_to_main_sender.send(command))
|
drop(worker_to_main_sender.send(command))
|
||||||
}));
|
}));
|
||||||
|
@ -122,7 +122,7 @@ impl SceneProxy {
|
||||||
/// Returns a copy of the wrapped scene.
|
/// Returns a copy of the wrapped scene.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn copy_scene(&self) -> Scene {
|
pub fn copy_scene(&self) -> Scene {
|
||||||
let (sender, receiver) = crossbeam_channel::bounded(MAX_MESSAGES_IN_FLIGHT);
|
let (sender, receiver) = flume::bounded(MAX_MESSAGES_IN_FLIGHT);
|
||||||
self.sender.send(MainToWorkerMsg::CopyScene(sender)).unwrap();
|
self.sender.send(MainToWorkerMsg::CopyScene(sender)).unwrap();
|
||||||
receiver.recv().unwrap()
|
receiver.recv().unwrap()
|
||||||
}
|
}
|
||||||
|
|
|
@ -646,7 +646,7 @@ impl<D> Renderer<D> where D: Device {
|
||||||
location: TextureLocation { page: TexturePageId(!0), rect: RectI::default() },
|
location: TextureLocation { page: TexturePageId(!0), rect: RectI::default() },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let mut render_target =
|
let render_target =
|
||||||
&mut self.core.render_targets[render_target_id.render_target as usize];
|
&mut self.core.render_targets[render_target_id.render_target as usize];
|
||||||
debug_assert_eq!(render_target.location.page, TexturePageId(!0));
|
debug_assert_eq!(render_target.location.page, TexturePageId(!0));
|
||||||
render_target.location = location;
|
render_target.location = location;
|
||||||
|
|
|
@ -49,7 +49,8 @@ impl<'a> RenderCommandListener<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Options that influence scene building.
|
/// Options that influence scene building.
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Copy, Default)]
|
||||||
|
#[repr(C)]
|
||||||
pub struct BuildOptions {
|
pub struct BuildOptions {
|
||||||
/// A global transform to be applied to the scene.
|
/// A global transform to be applied to the scene.
|
||||||
pub transform: RenderTransform,
|
pub transform: RenderTransform,
|
||||||
|
@ -71,7 +72,7 @@ impl BuildOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A global transform to apply to the scene.
|
/// A global transform to apply to the scene.
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum RenderTransform {
|
pub enum RenderTransform {
|
||||||
/// A 2D transform.
|
/// A 2D transform.
|
||||||
Transform2D(Transform2F),
|
Transform2D(Transform2F),
|
||||||
|
|
|
@ -587,7 +587,7 @@ impl Palette {
|
||||||
texture_manager: &mut PaintTextureManager,
|
texture_manager: &mut PaintTextureManager,
|
||||||
render_transform: Transform2F) {
|
render_transform: Transform2F) {
|
||||||
for (paint, metadata) in self.paints.iter().zip(paint_metadata.iter_mut()) {
|
for (paint, metadata) in self.paints.iter().zip(paint_metadata.iter_mut()) {
|
||||||
let mut color_texture_metadata = match metadata.color_texture_metadata {
|
let color_texture_metadata = match metadata.color_texture_metadata {
|
||||||
None => continue,
|
None => continue,
|
||||||
Some(ref mut color_texture_metadata) => color_texture_metadata,
|
Some(ref mut color_texture_metadata) => color_texture_metadata,
|
||||||
};
|
};
|
||||||
|
@ -843,7 +843,7 @@ impl GradientTileBuilder {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut data = self.tiles.last_mut().unwrap();
|
let data = self.tiles.last_mut().unwrap();
|
||||||
let location = TextureLocation {
|
let location = TextureLocation {
|
||||||
page: data.page,
|
page: data.page,
|
||||||
rect: RectI::new(vec2i(0, data.next_index as i32),
|
rect: RectI::new(vec2i(0, data.next_index as i32),
|
||||||
|
|
|
@ -34,6 +34,8 @@ use std::u64;
|
||||||
|
|
||||||
static NEXT_SCENE_ID: AtomicUsize = AtomicUsize::new(0);
|
static NEXT_SCENE_ID: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
|
const MAX_MESSAGES_IN_FLIGHT: usize = 1024;
|
||||||
|
|
||||||
/// The vector scene to be rendered.
|
/// The vector scene to be rendered.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Scene {
|
pub struct Scene {
|
||||||
|
@ -370,11 +372,29 @@ impl Scene {
|
||||||
renderer: &mut Renderer<D>,
|
renderer: &mut Renderer<D>,
|
||||||
build_options: BuildOptions,
|
build_options: BuildOptions,
|
||||||
executor: E)
|
executor: E)
|
||||||
where D: Device, E: Executor {
|
where D: Device, E: Executor + Send {
|
||||||
let commands = self.build_into_vector(renderer, build_options, executor);
|
std::thread::scope(move |scope| {
|
||||||
renderer.begin_scene();
|
let (tx, rx) = flume::bounded(MAX_MESSAGES_IN_FLIGHT);
|
||||||
commands.into_iter().for_each(|command| renderer.render_command(&command));
|
|
||||||
renderer.end_scene();
|
let level = renderer.mode().level;
|
||||||
|
|
||||||
|
// TODO: avoid this auxiliary thread
|
||||||
|
scope.spawn(move || {
|
||||||
|
let listener = RenderCommandListener::new(Box::new(move |command| {
|
||||||
|
tx.send(command).unwrap()
|
||||||
|
}));
|
||||||
|
let mut sink = SceneSink::new(listener, level);
|
||||||
|
self.build(build_options, &mut sink, &executor);
|
||||||
|
});
|
||||||
|
|
||||||
|
renderer.begin_scene();
|
||||||
|
|
||||||
|
for command in rx {
|
||||||
|
renderer.render_command(&command);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.end_scene();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue