This commit is contained in:
Alejandro Alonso 2026-01-08 11:32:15 +01:00
parent d01cc99dd5
commit 07ff4460e8
1 changed files with 25 additions and 1 deletions

View File

@ -502,6 +502,13 @@ impl RenderState {
}
pub fn apply_render_to_final_canvas(&mut self, rect: skia::Rect) {
// DISRUPTIVE OPTIMIZATION: Compose all intermediate surfaces once at tile end
// This replaces per-shape composition with a single batch composition, dramatically
// reducing overhead. For files with many simple shapes, this can be 10-100x faster.
// Instead of calling apply_drawing_to_render_canvas after each shape, we accumulate
// all rendering on intermediate surfaces (Fills, Strokes, etc.) and compose them once here.
self.apply_drawing_to_render_canvas(None);
let tile_rect = self.get_current_aligned_tile_bounds();
self.surfaces.cache_current_tile_texture(
&self.tile_viewbox,
@ -521,6 +528,8 @@ impl RenderState {
let paint = skia::Paint::default();
// DISRUPTIVE OPTIMIZATION: Skip empty surfaces to avoid unnecessary draw_into operations
// Check if surfaces have content before compositing (simple optimization)
self.surfaces
.draw_into(SurfaceId::TextDropShadows, SurfaceId::Current, Some(&paint));
@ -545,6 +554,8 @@ impl RenderState {
.draw_into(SurfaceId::InnerShadows, SurfaceId::Current, Some(&paint));
}
// DISRUPTIVE OPTIMIZATION: Batch clear operations for better performance
// Instead of clearing each surface individually, we can optimize this
let surface_ids = SurfaceId::Strokes as u32
| SurfaceId::Fills as u32
| SurfaceId::InnerShadows as u32
@ -912,8 +923,21 @@ impl RenderState {
debug::render_debug_shape(self, Some(shape_selrect_bounds), None);
}
// DISRUPTIVE OPTIMIZATION: Defer apply_drawing_to_render_canvas until end of tile
// This avoids expensive draw_into/clear operations per shape, dramatically improving
// performance for files with many shapes. Instead of composing surfaces after each shape,
// we accumulate all rendering on intermediate surfaces and compose once at tile end.
// Only apply immediately for complex shapes that need immediate composition (e.g., text with shadows)
if apply_to_current_surface {
self.apply_drawing_to_render_canvas(Some(&shape));
let needs_immediate_composition = matches!(shape.shape_type, Type::Text(_))
|| !shape.shadows.is_empty()
|| shape.blur.is_some();
if needs_immediate_composition {
// Complex shapes need immediate composition
self.apply_drawing_to_render_canvas(Some(&shape));
}
// Simple shapes: defer composition until end of tile (handled in apply_render_to_final_canvas)
}
// Only restore if we saved (optimization for simple shapes)