jrmuizel / raqote

Rust 2D graphics library
BSD 3-Clause "New" or "Revised" License
1.04k stars 59 forks source link

composite slow? #159

Closed FloVanGH closed 2 years ago

FloVanGH commented 4 years ago

OrbTk draws slow by dragging a widget. In this case the mouse move will trigger redraw and in this case it is slow. I profiles the application and most time is spent on the composite method of raqote. Have you any idea how it could be improved or any plans?

image

jrmuizel commented 4 years ago

Sorry, I didn't see this earlier. What's the best way for me to reproduce this?

FloVanGH commented 4 years ago

Checkout the develop branch of OrbTk start the widgets example cargo run --example widgets --release. And move the slider widget.

image

There is also a branch memory-fix there it is a little bit faster.

jrmuizel commented 4 years ago

Does OrbTK have an invalidation mechanism that lets it only draw the widgets that have changed or does it redraw everything if anything changes?

FloVanGH commented 4 years ago

At the moment it draws everything new. I was thinking a lot how to handle this. The problem is I can not only check if a widget has changes, if the size position is changed I have to check and redraw all parents and possible widgets in the near and check if they now overlap.

jrmuizel commented 4 years ago

Ok, well I landed https://github.com/jrmuizel/raqote/commit/2f5ce264670423da5ca1eb215278824616e7e00f. With that, plus the following change to OrbTK to use fill_rect() when possible reduces the time spent in DrawTarget::fill()/composite quite a bit.

diff --git a/crates/api/src/render_object/rectangle.rs b/crates/api/src/render_object/rectangle.rs
index e787ea15..67a928e3 100644
--- a/crates/api/src/render_object/rectangle.rs
+++ b/crates/api/src/render_object/rectangle.rs
@@ -211,21 +211,20 @@ impl RenderObject for RectangleRenderObject {
             ctx.render_context_2_d().fill();
         } else if has_thickness {
             self.render_bordered_rect_path(
                 ctx.render_context_2_d(),
                 Rectangle::new(*global_position + bounds.position(), bounds.size()),
                 background,
                 border_brush,
                 border_thickness,
             );
         } else {
-            ctx.render_context_2_d().rect(
+            ctx.render_context_2_d().set_fill_style(background);
+            ctx.render_context_2_d().fill_rect(
                 global_position.x() + bounds.x(),
                 global_position.y() + bounds.y(),
                 bounds.width(),
                 bounds.height(),
             );
-            ctx.render_context_2_d().set_fill_style(background);
-            ctx.render_context_2_d().fill();
         }
     }
 }
FloVanGH commented 4 years ago

Thank you 🙂. I will test it. What I really like on raqote is its portability. I was thinking about to use fontkit in raqote for all platforms except of Redox. Could it be faster? Do you have any experience with it?

jrmuizel commented 4 years ago

The fontkit support in raqote is currently not very good. It has some correctness issues and is slow. My current plan is to try to split out the font code from https://github.com/servo/webrender/tree/master/webrender/src/platform into a separate crate and use that for font rendering instead of font-kit. That should give speed, correctness and make it so that text properly matches platform rendering.

Unfortunately, I have no timeline for when I'll get to that.

Also a way to improve the performance further in the case you mentioned above is to use BlendMode::Src when drawing the background instead of BlendMode::SrcOver

Shnatsel commented 4 years ago

Benchmarks of blending operations on various libraries also point to raqote being considerably slower than the alternatives, sometimes as much as 20x: https://github.com/RazrFalcon/tiny-skia/blob/master/benches/README.md

Tested on raqote 0.8.0 and sw-composite 0.7.12 from crates.io