Integrate Vello for vector rendering (#1802)

* Start integrating vello into render pipeline

Cache vello render creation

Implement viewport navigation

Close vello path

Add transform parameter to vello render pass

* Fix render node types

* Fix a bunch of bugs in the path translation

* Avoid panic on empty document

* Fix rendering of holes

* Implement image rendering

* Implement graph recompilation afer editor api change

* Implement preferences toggle for using vello as the renderer

* Make surface creation optional

* Feature gate vello usages

* Implement skeleton for radial gradient

* Rename vello preference

* Fix some gradients

* Only update monitor nodes on graph recompile

* Fix warnings + remove dead code

* Update everything except for thumbnails after a node graph evaluation

* Fix missing click targets for Image frames

* Improve perfamance by removing unecessary widget updates

* Fix node graph paning

* Fix thumbnail loading

* Implement proper hash for vector modification

* Fix test and warnings

* Code review

* Fix dep

* Remove warning

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Dennis Kobert
2024-07-22 01:56:29 -07:00
committed by GitHub
co-authored by Keavon Chambers
parent 8e774efe9d
commit ab71d26d84
41 changed files with 805 additions and 758 deletions
+35 -11
View File
@@ -10,7 +10,7 @@ use core::future::Future;
use core::hash::{Hash, Hasher};
use core::pin::Pin;
use core::ptr::addr_of;
use glam::DAffine2;
use glam::{DAffine2, UVec2};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
@@ -26,6 +26,7 @@ impl core::fmt::Display for SurfaceId {
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SurfaceFrame {
pub surface_id: SurfaceId,
pub resolution: UVec2,
pub transform: DAffine2,
}
@@ -51,11 +52,23 @@ unsafe impl StaticType for SurfaceFrame {
type Static = SurfaceFrame;
}
impl<S> From<SurfaceHandleFrame<S>> for SurfaceFrame {
pub trait Size {
fn size(&self) -> UVec2;
}
#[cfg(target_arch = "wasm32")]
impl Size for web_sys::HtmlCanvasElement {
fn size(&self) -> UVec2 {
UVec2::new(self.width(), self.height())
}
}
impl<S: Size> From<SurfaceHandleFrame<S>> for SurfaceFrame {
fn from(x: SurfaceHandleFrame<S>) -> Self {
Self {
surface_id: x.surface_handle.surface_id,
transform: x.transform,
resolution: x.surface_handle.surface.size(),
}
}
}
@@ -70,6 +83,12 @@ pub struct SurfaceHandle<Surface> {
// #[cfg(target_arch = "wasm32")]
// unsafe impl<T: dyn_any::WasmNotSync> Sync for SurfaceHandle<T> {}
impl<S: Size> Size for SurfaceHandle<S> {
fn size(&self) -> UVec2 {
self.surface.size()
}
}
unsafe impl<T: 'static> StaticType for SurfaceHandle<T> {
type Static = SurfaceHandle<T>;
}
@@ -162,8 +181,9 @@ impl<T: NodeGraphUpdateSender> NodeGraphUpdateSender for std::sync::Mutex<T> {
}
}
pub trait GetImaginatePreferences {
fn get_host_name(&self) -> &str;
pub trait GetEditorPreferences {
fn hostname(&self) -> &str;
fn use_vello(&self) -> bool;
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
@@ -196,10 +216,14 @@ impl NodeGraphUpdateSender for Logger {
struct DummyPreferences;
impl GetImaginatePreferences for DummyPreferences {
fn get_host_name(&self) -> &str {
impl GetEditorPreferences for DummyPreferences {
fn hostname(&self) -> &str {
"dummy_endpoint"
}
fn use_vello(&self) -> bool {
false
}
}
pub struct EditorApi<Io> {
@@ -208,8 +232,8 @@ pub struct EditorApi<Io> {
/// Gives access to APIs like a rendering surface (native window handle or HTML5 canvas) and WGPU (which becomes WebGPU on web).
pub application_io: Option<Arc<Io>>,
pub node_graph_message_sender: Box<dyn NodeGraphUpdateSender + Send + Sync>,
/// Imaginate preferences made available to the graph through the [`WasmEditorApi`].
pub imaginate_preferences: Box<dyn GetImaginatePreferences + Send + Sync>,
/// Editor preferences made available to the graph through the [`WasmEditorApi`].
pub editor_preferences: Box<dyn GetEditorPreferences + Send + Sync>,
}
impl<Io> Eq for EditorApi<Io> {}
@@ -220,7 +244,7 @@ impl<Io: Default> Default for EditorApi<Io> {
font_cache: FontCache::default(),
application_io: None,
node_graph_message_sender: Box::new(Logger),
imaginate_preferences: Box::new(DummyPreferences),
editor_preferences: Box::new(DummyPreferences),
}
}
}
@@ -230,7 +254,7 @@ impl<Io> Hash for EditorApi<Io> {
self.font_cache.hash(state);
self.application_io.as_ref().map_or(0, |io| io.as_ref() as *const _ as usize).hash(state);
(self.node_graph_message_sender.as_ref() as *const dyn NodeGraphUpdateSender).hash(state);
(self.imaginate_preferences.as_ref() as *const dyn GetImaginatePreferences).hash(state);
(self.editor_preferences.as_ref() as *const dyn GetEditorPreferences).hash(state);
}
}
@@ -239,7 +263,7 @@ impl<Io> PartialEq for EditorApi<Io> {
self.font_cache == other.font_cache
&& self.application_io.as_ref().map_or(0, |io| addr_of!(io) as usize) == other.application_io.as_ref().map_or(0, |io| addr_of!(io) as usize)
&& std::ptr::eq(self.node_graph_message_sender.as_ref() as *const _, other.node_graph_message_sender.as_ref() as *const _)
&& std::ptr::eq(self.imaginate_preferences.as_ref() as *const _, other.imaginate_preferences.as_ref() as *const _)
&& std::ptr::eq(self.editor_preferences.as_ref() as *const _, other.editor_preferences.as_ref() as *const _)
}
}