-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
The logic for this changed recently with flutter/engine#32378, though I've confirmed it doesn't work correctly before that point too.
Each Layer object has a unique id that is assigned when it is created. For most layers, when it is pushed we also add the old layer. This allows us to reuse the ID and recognize that the layer has just had some properties updated - a change in opacity or offset.
While the framework has a concept of a PictureLayer, these are added to the scene directly as pictures, and there is no associated engine object:
Now the picture itself has a stable id if it is unchanged, backed by the display list today, but every time it is pushed we generate a new DisplayListLayer with a new id. Normally this is fine, since if we specifically ask the raster cache to cache a display list, it will use the display list id as a key:
However, if instead we try to cache a layer, perhaps from an OpacityLayer, then we'll go through the following code which uses the layer id and not the DisplayList id.
As long as the direct descendant of an Opacity (or other) is a PictureLayer, we will always thrash the raster cache on each frame. See also #101597, which I may have misdiagnosed. Inserting the repaint boundary inserts an OffsetLayer which does not have this problem.
So we have a few options here:
-
Break the scene builder API so that we return the engine picture layer / display list layer as an opaque object as well as update the method to accept and sync ids if the pictures/display list are identical. This is the strategy we took for the rest of the API.
-
Update the child raster caching strategy to conditionally use the display list id, or to delegate to each child layer somehow. Less sure about this one, I think in theory we would also have to change the type of the raster cache key to ensure there were no collisions between display list and layer ids.