-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
Due to Skia's implementation of SkMatrixImageFilter, the filterQuality parameter on the Transform widget is actually very inefficient. This can be verified by taking a capture of a Flutter application with RenderDoc.
Skia's implementation creates an offscreen surface to render the transformed image into. This can be simplified greatly, especially since the source image comes from the raster cache.
In the worst case scenario, Flutter rasterizer caches the child layer, then takes the rasterizer cached image and draws it onto a new SkSurface with the transform, and then draws it to the final canvas during compositing. In the best case scenario, the child layer is already cached.
This extra copy makes the transform extremely expensive, even for static content. ImageFilterLayer is supposed to be a way to efficiently transform and scale static content without tons of raster cache misses, but it unfortunately isn't worthwhile as it doesn't scale due to this issue. It also forcefully caches itself if the filter doesn't change, which is terrible for animations because the raster cache drops the child content if the animation is still for a certain number of frames.
When using a lot of layers, performance suffers compared to using a canvas with transforms & drawImage. The only reason why the canvas solution isn't viable is because Picture.toImage is async, which gives a frame of delay before the image can be used for drawing. The raster cache doesn't have this issue.
I would love to be able to tell TransformLayer to rasterize it's child with one matrix (to add a scale factor to the cache entry's resolution) and then draw the raster cached content with another matrix. This would also be very helpful for ScaleTransition, as you could avoid thrashing the raster cache when scaling something up or down.
cc @flar