-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
Reproduction code (only depends on dart:ui and a large image):
Copied from the documentation comment on main():
Raw, dart:ui-only example of an issue with opacity layers & the rasterizer cache.
Works best on Desktop, controls need to be changed for Android & iOS.
Web untested.
Controls:
Left Click - Add Opacity Layer
Right Click - Remove Opacity Layer
Expected Behavior:
Adding opacity layers does not increase the total memory usage.
Actual Behavior:
Each opacity layer causes the RasterCache to allocate a new 4,000 by 2,000 texture.
One would expect that nested opacity layers would collapse into a single (equivalent) layer, and one would expect that a picture layer displaying a simple image could merge with the opacity layer, resulting in a call to drawImage with a Paint applying the equivalent opacity.
Why does this matter?
There are many scenarios where a developer can place one (or more) opacity layers around a simple image. For example, the built-in FadeInImage widget, which uses FadeTransition, which eventually produces an opacity layer in RenderAnimatedOpacity.
Apps fade in images a lot. An image-heavy application (e.g. our application) can vary in memory usage wildly, regardless of the Flutter-level ImageCache.
Additionally, an app with an infinite scrolling list of images being faded in will hit memory limits on fast flings. Not because of image loading, but because the raster cache is unbounded when used in conjunction with OpacityLayer. This is also why video memory usage can seemingly fluctuate, or fail to match the exact number of images loaded.
What can be done?
OpacityLayer currently delegates out to the RasterCache, drawing the child layer with the specified paint.
This can be changed to allow layers to:
- Trivially combine paints (OpacityLayer -> OpacityLayer situation)
- Circumvent the need for the raster cache by combining paints together, if compatible (OpacityLayer -> simple PictureLayer situation)
Perhaps an ImageLayer can be introduced, to make this situation easier to optimize, since Skia Pictures are opaque (can't get list of Ops out).
cc @dnfield
also goodnight, it's 1:30am.