Repository: flutter
Issue: Provide a more transparent mechanism to manipulate cached children
Labels: c: new feature,engine,c: proposal,P3,team-engine,triaged-engine

This issue is closely related to https://github.com/flutter/flutter/issues/91923 but whereas the former issue is focused on consolidating the logic, this Issue is more about upgrading that logic with a more global strategy that will look at interactions between requests for caching. The prior issue is already being worked on in https://github.com/flutter/engine/pull/31892.

The current RasterCache mechanism and solutions are focused around a limited amount of communication between layers.

Staring with a simple example, a case where a parent layer wants to apply some filtering operation to its children is handled by attempting to cache the children. Often there is just a single child as most Flutter widgets which specify these operations only have a single child, but due to the mechanics of compositing as the layer tree is assembled, a single widget child can explode into multiple layer children. Still, it is quite common for a parent to have a single child.

Most leaf children to which these filtering operations are applied are DisplayLists. These children can quite easily cache themselves if they have any complexity, but their decision is independent from a parent filtering layer's individual intentions to cache its children.

This confusion over who will do the caching currently can result in a lot of double-caching where both enter themselves in the cache, but during the Paint cycle, only one of the cache entries is used. Some tweaks have reduced the impact of this, and hopefully https://github.com/flutter/engine/pull/31892 will end the double-caching once and for all. But, this points out that there isn't really good communication between the layers and https://github.com/flutter/engine/pull/31892 only solves it in a very basic way by preventing children from caching if their parent has already done so.

The one case where there is any communication between the children and their parents to help simplify this situation is for an OpacityLayer which asks its children if they can apply the opacity themselves as they render - and it avoids caching its children in that case. If a DisplayList is a child of an OpacityLayer then the Opacity parent should be able to tell the DL child to just "render with this additional opacity reduction". That mostly works, but the communication back and forth in this case is not well managed. If the DL is planning to cache then it puts the Opacity parent through a number of frames of "not yet" on that promise before we end up with a frame where both are deciding to handle the caching themselves. This could be adjusted by having the DL child cache itself early, but the caching mechanisms don't current support that "threshold" customization. Also, there are variants of this scenario where the DL can apply the opacity itself whether or not it caches and where the DL cannot be cached for some reason and so we can't just completely eliminate one of their intentions to cache in favor of the other as the interplay may require both to at least try.

Some other layers may want to also pass along their filtering operation to the child - ColorFilterLayer and ImageFilterLayer for example. These filtering layers don't yet have the optimization to pass their modification along to their children. The layer that is doing a bitmap transform of the child (currently ImageFilterLayer with a TransformFilter, but this could be changed to a type of TransformLayer that intends to use a bitmap operation) might also want to involve itself in this "master planning".

Whether or not all of the layers that can use a peephole optimization to combine operations with their children have a mechanism to do so in isolation, we then have the issue of multiple enclosing filtering operations that would need to be coordinated with each other along with their children. Can they all be applied at once to their cached child? Are there ordering considerations involved. These kinds of decisions require some sort of centralized collection of information about the filtering modifications in order to decide at which level we might cache for maximum collapsing of the multiple operations.

This issue is primarily about the creation of a centralized multi-layer-aware caching strategy mechanism most likely to be applied within the context of https://github.com/flutter/engine/pull/31892