servo / pathfinder

A fast, practical GPU rasterizer for fonts and vector graphics
Apache License 2.0
3.56k stars 198 forks source link

Image::new is very slow #447

Closed colorhook closed 3 years ago

colorhook commented 3 years ago
let start = std::time::Instant::now();
pixels.hash(&mut pixels_hasher);
let delta = std::time::Instant::now() - start;
println!("image pixels.hash cost: {}ms", delta.as_micros() as f32 / 1000.0);

In release version:

output:  image pixels.hash cost: 20.289ms
s3bk commented 3 years ago

That should probably be precomputed…

colorhook commented 3 years ago

Follow the BitmapData definition in Web Standard, I maintain the pixels by TypeArray in Javascript. I create Pattern by Vec dynamically each frame and call draw_subimage to draw Image.

I cannot precompute and cache the Image because the TypeArray would be changed in JavaScript

colorhook commented 3 years ago

in CanvasRenderingContext2D put_image_data method, Image::new called also:

pub fn put_image_data<L>(&mut self, image_data: ImageData, dest_location: L)
                             where L: CanvasImageDestLocation {
    let origin = dest_location.origin();
    let size = dest_location.size().unwrap_or(image_data.size.to_f32());
    let pattern = Pattern::from_image(image_data.into_image());
    let paint_id = self.canvas.scene.push_paint(&Paint::from_pattern(pattern));
    let draw_path = DrawPath::new(Outline::from_rect(RectF::new(origin, size)), paint_id);
    self.canvas.scene.push_draw_path(draw_path);
}
s3bk commented 3 years ago

Creating an Image from data is expensive, there is nothing one can do about it apart from not doing it. In the best case the image encoding matches the texture and the trans-coding can be skipped, but that is not implemented yet.

colorhook commented 3 years ago

I use caching layer to avoid .drawImage() performance issues, thanks!