From 1cd3c087366fdec02aaeddc11b3b58a2ac7f6fae Mon Sep 17 00:00:00 2001 From: Aitor Moreno Date: Thu, 8 May 2025 13:30:47 +0200 Subject: [PATCH] WIP --- frontend/resources/wasm-playground/js/lib.js | 13 +++ frontend/resources/wasm-playground/rects.html | 15 ++- render-wasm/Cargo.lock | 108 +++++++++++++++++- render-wasm/Cargo.toml | 2 + render-wasm/src/render.rs | 46 +++++--- render-wasm/src/shapes/modifiers.rs | 5 +- .../src/shapes/modifiers/flex_layout.rs | 8 +- .../src/shapes/modifiers/grid_layout.rs | 13 ++- render-wasm/src/state.rs | 8 +- 9 files changed, 182 insertions(+), 36 deletions(-) diff --git a/frontend/resources/wasm-playground/js/lib.js b/frontend/resources/wasm-playground/js/lib.js index 124b86a3c3..f7d5349469 100644 --- a/frontend/resources/wasm-playground/js/lib.js +++ b/frontend/resources/wasm-playground/js/lib.js @@ -79,6 +79,19 @@ function getHeapU32() { return Module.HEAPU32; } +export function clearShapeFills() { + Module._clear_shape_fills(); +} + +export function addShapeSolidFill(argb) { + const ptr = allocBytes(176); + const heap = getHeapU32(); + const dv = new DataView(heap.buffer); + dv.setUint8(ptr, 0x00, true); + dv.setUint32(ptr + 4, argb, true); + Module._add_shape_fill(); +} + export function setShapeChildren(shapeIds) { const offset = allocBytes(shapeIds.length * 16); const heap = getHeapU32(); diff --git a/frontend/resources/wasm-playground/rects.html b/frontend/resources/wasm-playground/rects.html index 120ee688b6..738ef85e1b 100644 --- a/frontend/resources/wasm-playground/rects.html +++ b/frontend/resources/wasm-playground/rects.html @@ -25,7 +25,7 @@ diff --git a/render-wasm/Cargo.lock b/render-wasm/Cargo.lock index 0416a66974..e1aef7d086 100644 --- a/render-wasm/Cargo.lock +++ b/render-wasm/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "adler2" @@ -781,7 +781,19 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] @@ -1337,7 +1349,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", - "rand", + "rand 0.8.5", ] [[package]] @@ -1393,6 +1405,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + [[package]] name = "prettyplease" version = "0.2.24" @@ -1439,13 +1460,39 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +dependencies = [ + "rand_chacha", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", ] [[package]] @@ -1454,6 +1501,15 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.2", +] + [[package]] name = "redox_syscall" version = "0.5.7" @@ -1469,7 +1525,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom", + "getrandom 0.2.15", "libredox", "thiserror", ] @@ -1511,6 +1567,8 @@ dependencies = [ "cargo-watch", "gl", "indexmap", + "rand 0.9.1", + "rustc-hash", "skia-safe", "uuid", ] @@ -1955,7 +2013,7 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ - "getrandom", + "getrandom 0.2.15", ] [[package]] @@ -1986,6 +2044,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasm-bindgen" version = "0.2.100" @@ -2344,6 +2411,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.6.0", +] + [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -2444,6 +2520,26 @@ dependencies = [ "zvariant", ] +[[package]] +name = "zerocopy" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", +] + [[package]] name = "zvariant" version = "5.2.0" diff --git a/render-wasm/Cargo.toml b/render-wasm/Cargo.toml index 72570a1274..1d2081d767 100644 --- a/render-wasm/Cargo.toml +++ b/render-wasm/Cargo.toml @@ -20,6 +20,8 @@ path = "src/main.rs" base64 = "0.22.1" gl = "0.14.0" indexmap = "2.7.1" +rand = "0.9.1" +rustc-hash = "2.1.1" skia-safe = { version = "0.81.0", default-features = false, features = ["gl", "svg", "textlayout", "binary-cache"]} uuid = { version = "1.11.0", features = ["v4"] } diff --git a/render-wasm/src/render.rs b/render-wasm/src/render.rs index aaf825d356..1a15c16a6b 100644 --- a/render-wasm/src/render.rs +++ b/render-wasm/src/render.rs @@ -1,3 +1,4 @@ +use rustc_hash::FxBuildHasher; use skia_safe::{self as skia, Matrix, RRect, Rect}; use crate::uuid::Uuid; @@ -20,10 +21,11 @@ mod surfaces; mod text; mod tiles; -use crate::shapes::{modified_children_ids, Corners, Shape, StructureEntry, Type}; +use crate::shapes::{modified_children_ids, Corners, Fill, Shape, SolidColor, StructureEntry, Type}; use gpu_state::GpuState; use options::RenderOptions; use surfaces::{SurfaceId, Surfaces}; +use rand::Rng; pub use blend::BlendMode; pub use fonts::*; @@ -429,7 +431,7 @@ impl RenderState { pub fn start_render_loop( &mut self, - tree: &mut HashMap, + tree: &mut HashMap, modifiers: &HashMap, structure: &HashMap>, timestamp: i32, @@ -496,7 +498,7 @@ impl RenderState { pub fn process_animation_frame( &mut self, - tree: &mut HashMap, + tree: &mut HashMap, modifiers: &HashMap, structure: &HashMap>, timestamp: i32, @@ -595,7 +597,7 @@ impl RenderState { pub fn render_shape_tree( &mut self, - tree: &mut HashMap, + tree: &mut HashMap, modifiers: &HashMap, structure: &HashMap>, timestamp: i32, @@ -643,6 +645,24 @@ impl RenderState { .to_string(), )?; + // let element = &mut Shape::new(node_id); + // element.parent_id = Some(Uuid::nil()); + // // element.shape_type = Type::Rect(CustomRect::Rect::default()); + // let mut rng = rand::thread_rng(); + // element.selrect = Rect::from_xywh( + // rng.gen_range(0..=2498) as f32, + // rng.gen_range(0..=1321) as f32, + // rng.gen_range(20..=100) as f32, + // rng.gen_range(20..=100) as f32, + // ); + // let mut rng = rand::thread_rng(); + // let a = rng.gen_range(16..=255); + // let r = rng.gen_range(0..=255); + // let g = rng.gen_range(0..=255); + // let b = rng.gen_range(0..=255); + // let c = skia::Color::from_argb(a, r, g, b); + // element.add_fill(Fill::Solid(SolidColor(c))); + // If the shape is not in the tile set, then we update // it. if let None = self.tiles.get_tiles_of(node_id) { @@ -745,12 +765,12 @@ impl RenderState { } // We try to avoid doing too many calls to get_time - if i % NODE_BATCH_THRESHOLD == 0 - && performance::get_time() - timestamp > MAX_BLOCKING_TIME_MS - { - return Ok(()); - } - i += 1; + // if i % NODE_BATCH_THRESHOLD == 0 + // && performance::get_time() - timestamp > MAX_BLOCKING_TIME_MS + // { + // return Ok(()); + // } + // i += 1; } performance::end_measure!("render_shape_tree::uncached"); let tile_rect = self.get_current_tile_bounds(); @@ -850,7 +870,7 @@ impl RenderState { pub fn rebuild_tiles_shallow( &mut self, - tree: &mut HashMap, + tree: &mut HashMap, modifiers: &HashMap, structure: &HashMap>, ) { @@ -880,7 +900,7 @@ impl RenderState { pub fn rebuild_tiles( &mut self, - tree: &mut HashMap, + tree: &mut HashMap, modifiers: &HashMap, structure: &HashMap>, ) { @@ -909,7 +929,7 @@ impl RenderState { pub fn rebuild_modifier_tiles( &mut self, - tree: &mut HashMap, + tree: &mut HashMap, modifiers: &HashMap, ) { for (uuid, matrix) in modifiers { diff --git a/render-wasm/src/shapes/modifiers.rs b/render-wasm/src/shapes/modifiers.rs index 491b5ba7e6..8e7b12fa1f 100644 --- a/render-wasm/src/shapes/modifiers.rs +++ b/render-wasm/src/shapes/modifiers.rs @@ -5,6 +5,7 @@ mod flex_layout; mod grid_layout; use common::GetBounds; +use rustc_hash::FxBuildHasher; use crate::math::{identitish, Bounds, Matrix, Point}; use crate::shapes::{ @@ -16,7 +17,7 @@ use crate::uuid::Uuid; fn propagate_children( shape: &Shape, - shapes: &HashMap, + shapes: &HashMap, parent_bounds_before: &Bounds, parent_bounds_after: &Bounds, transform: Matrix, @@ -83,7 +84,7 @@ fn propagate_children( fn calculate_group_bounds( shape: &Shape, - shapes: &HashMap, + shapes: &HashMap, bounds: &HashMap, structure: &HashMap>, ) -> Option { diff --git a/render-wasm/src/shapes/modifiers/flex_layout.rs b/render-wasm/src/shapes/modifiers/flex_layout.rs index 51022a35fb..3281b6c039 100644 --- a/render-wasm/src/shapes/modifiers/flex_layout.rs +++ b/render-wasm/src/shapes/modifiers/flex_layout.rs @@ -1,4 +1,6 @@ #![allow(dead_code)] +use rustc_hash::FxBuildHasher; + use crate::math::{self as math, Bounds, Matrix, Point, Vector, VectorExt}; use crate::shapes::{ modified_children_ids, AlignContent, AlignItems, AlignSelf, FlexData, JustifyContent, @@ -178,7 +180,7 @@ fn initialize_tracks( layout_bounds: &Bounds, layout_axis: &LayoutAxis, flex_data: &FlexData, - shapes: &HashMap, + shapes: &HashMap, bounds: &HashMap, structure: &HashMap>, ) -> Vec { @@ -420,7 +422,7 @@ fn calculate_track_data( layout_data: &LayoutData, flex_data: &FlexData, layout_bounds: &Bounds, - shapes: &HashMap, + shapes: &HashMap, bounds: &HashMap, structure: &HashMap>, ) -> Vec { @@ -551,7 +553,7 @@ pub fn reflow_flex_layout( shape: &Shape, layout_data: &LayoutData, flex_data: &FlexData, - shapes: &HashMap, + shapes: &HashMap, bounds: &mut HashMap, structure: &HashMap>, ) -> VecDeque { diff --git a/render-wasm/src/shapes/modifiers/grid_layout.rs b/render-wasm/src/shapes/modifiers/grid_layout.rs index 66933b8360..c565a7b443 100644 --- a/render-wasm/src/shapes/modifiers/grid_layout.rs +++ b/render-wasm/src/shapes/modifiers/grid_layout.rs @@ -6,6 +6,7 @@ use crate::shapes::{ }; use crate::uuid::Uuid; use indexmap::IndexSet; +use rustc_hash::FxBuildHasher; use std::collections::{HashMap, VecDeque}; use super::common::GetBounds; @@ -40,7 +41,7 @@ fn calculate_tracks( grid_data: &GridData, layout_bounds: &Bounds, cells: &Vec, - shapes: &HashMap, + shapes: &HashMap, bounds: &HashMap, ) -> Vec { let layout_size = if is_column { @@ -105,7 +106,7 @@ fn set_auto_base_size( column: bool, tracks: &mut Vec, cells: &Vec, - shapes: &HashMap, + shapes: &HashMap, bounds: &HashMap, ) { for cell in cells { @@ -156,7 +157,7 @@ fn set_auto_multi_span( column: bool, tracks: &mut Vec, cells: &Vec, - shapes: &HashMap, + shapes: &HashMap, bounds: &HashMap, ) { // Remove groups with flex (will be set in flex_multi_span) @@ -230,7 +231,7 @@ fn set_flex_multi_span( column: bool, tracks: &mut Vec, cells: &Vec, - shapes: &HashMap, + shapes: &HashMap, bounds: &HashMap, ) { // Remove groups without flex @@ -509,7 +510,7 @@ fn cell_bounds( fn create_cell_data<'a>( layout_bounds: &Bounds, children: &IndexSet, - shapes: &'a HashMap, + shapes: &'a HashMap, cells: &Vec, column_tracks: &Vec, row_tracks: &Vec, @@ -618,7 +619,7 @@ pub fn reflow_grid_layout<'a>( shape: &Shape, layout_data: &LayoutData, grid_data: &GridData, - shapes: &'a HashMap, + shapes: &'a HashMap, bounds: &mut HashMap, structure: &HashMap>, ) -> VecDeque { diff --git a/render-wasm/src/state.rs b/render-wasm/src/state.rs index 67f9129c17..c32dd545d0 100644 --- a/render-wasm/src/state.rs +++ b/render-wasm/src/state.rs @@ -1,4 +1,7 @@ use std::collections::HashMap; +use std::hash::RandomState; +use rustc_hash::FxBuildHasher; +use rustc_hash::FxHashMap; use skia_safe as skia; @@ -16,18 +19,19 @@ pub(crate) struct State<'a> { pub render_state: RenderState, pub current_id: Option, pub current_shape: Option<&'a mut Shape>, - pub shapes: HashMap, + pub shapes: HashMap, pub modifiers: HashMap, pub structure: HashMap>, } impl<'a> State<'a> { pub fn new(width: i32, height: i32, capacity: usize) -> Self { + let s = FxBuildHasher::default(); State { render_state: RenderState::new(width, height), current_id: None, current_shape: None, - shapes: HashMap::with_capacity(capacity), + shapes: HashMap::with_capacity_and_hasher(capacity, s), modifiers: HashMap::new(), structure: HashMap::new(), }