Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@ColdPaleLight
Copy link
Member

@ColdPaleLight ColdPaleLight commented Apr 18, 2022

fix flutter/flutter#101872

framework change probably looks like this

diff --git a/packages/flutter/lib/src/rendering/layer.dart b/packages/flutter/lib/src/rendering/layer.dart
index 4644180ddf..13115dafc8 100644
--- a/packages/flutter/lib/src/rendering/layer.dart
+++ b/packages/flutter/lib/src/rendering/layer.dart
@@ -711,7 +711,7 @@ class PictureLayer extends Layer {
   @override
   void addToScene(ui.SceneBuilder builder) {
     assert(picture != null);
-    builder.addPicture(Offset.zero, picture!, isComplexHint: isComplexHint, willChangeHint: willChangeHint);
+    engineLayer = builder.addPicture(Offset.zero, picture!, isComplexHint: isComplexHint, willChangeHint: willChangeHint, oldLayer: _engineLayer as ui.PictureEngineLayer?);
   }

Pre-launch Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I read the [Tree Hygiene] wiki page, which explains my responsibilities.
  • I read and followed the [Flutter Style Guide] and the [C++, Objective-C, Java style guides].
  • I listed at least one issue that this PR fixes in the description above.
  • I added new tests to check the change I am making or feature I am adding, or Hixie said the PR is test-exempt. See [testing the engine] for instructions on
    writing and running engine tests.
  • I updated/added relevant documentation (doc comments with ///).
  • I signed the [CLA].
  • All existing and new tests are passing.

@ColdPaleLight ColdPaleLight changed the title Recator API 'SceneBulder.addPicture' to return 'PictureEngineLayer' [WIP] Recator API 'SceneBulder.addPicture' to return 'PictureEngineLayer' Apr 18, 2022
@flutter-dashboard flutter-dashboard bot added the platform-web Code specifically for the web engine label Apr 18, 2022
Picture picture, {
bool isComplexHint = false,
bool willChangeHint = false,
PictureEngineLayer? oldLayer,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if oldLayer is needed in this place, it doesn't look useful. Probability it makes more sense not to add it?

/// {@macro dart.ui.sceneBuilder.oldLayer}
///
/// {@macro dart.ui.sceneBuilder.oldLayerVsRetained}
PictureEngineLayer addPicture(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since PictureEngineLayer is returned here and can't be null, the related logic in web_ui must also be implemented in this PR. And I'm not familiar with web_ui, so I'm not sure if my implementation is correct.

In addition, when this PR prepare to land, we need to temporarily disable some tests in packages/flutter/test/rendering/layers_test.dart, Because the FakeSceneBuilder.addPicture returns null
c.f.
https://github.com/flutter/flutter/blob/94d7f5e6724d3e0c627a9ceb27e294c5c12ddebb/packages/flutter/test/rendering/layers_test.dart#L751-L781

Maybe we can consider changing the return value here to PictureEngineLayer?, so that we don't have to change the implementation of web_ui, and we don't have to disable layers_test.dart

@jonahwilliams
Copy link
Contributor

I think the previous change you proposed would be much, much less intrusive than this change

@ColdPaleLight
Copy link
Member Author

ColdPaleLight commented Apr 18, 2022

I think the previous change you proposed would be much, much less intrusive than this change

The API changing in this proposal should not be too big, although it can't do the same as the previous proposal without change the API at all. But in this proposal, we only need to change the return value of SceneBuilder.addPicture from void to PictureEngineLayer or PictureEngineLayer?, and do not have to change the required arguments or optional arguments in SceneBuilder.addPicture . (oldLayer doesn't seem to be useful here, maybe we don't need to add it to the API, So we just need to change the return value type)

I verified that this proposal also works fine like the previous one.

@jonahwilliams
Copy link
Contributor

But compared to not having to update the API at all, it is a big change. Also consider that all code that manages pictures in the framework will now need to track the engine layer too.

@flar
Copy link
Contributor

flar commented Apr 18, 2022

Your suggestion for the framework change sounds like you haven't actually tested if this can work?

In particular, if the picture has been rebuilt then it should not be treated as an "oldLayer" when added to the tree. Where do you set engineLayer to null when the picture is rebuilt?

@flar
Copy link
Contributor

flar commented Apr 18, 2022

The RepaintBoundary solves that issue by actually not rebuilding its layers unless a child is modified. Solving this for non-RepaintBoundary objects would require any RenderObject that holds on to a picture to do such tracking - which means it needs to be a RepaintBoundary, or at least participate in the concept of which parts of the tree to rebuild to the same extent as RPB does.

@ColdPaleLight
Copy link
Member Author

Your suggestion for the framework change sounds like you haven't actually tested if this can work?

In particular, if the picture has been rebuilt then it should not be treated as an "oldLayer" when added to the tree. Where do you set engineLayer to null when the picture is rebuilt?

@flar I tested it and it works. In the current implementation of flutter, the PictureLayer of the framework does not hold the engineLayer, which results in that when its parent's addToScene is called, even if the PictureLayer's flag _needsAddToScene is false, its addToScene will also be called. And if PictureLayer also has engineLayer, then addRetained will be called in this case. So the key to making it work is to let PictureLayer hold its own engineLayer, so that the DisplayListLayer of the engine layer can be stable.Of course, like the previous proposal, this also requires flutter/flutter#101952

c.f.
https://github.com/flutter/flutter/blob/fd360c4a1d2418ad2d1ad83f7b5cc125696837f9/packages/flutter/lib/src/rendering/layer.dart#L532

@jonahwilliams
Copy link
Contributor

I sort of disagree with this implementation - we don't need the display list layer to be stable if the picture is stable. Assuming the user or the framework is keeping the picture stable, then the kLayer caching strategy should work. To do so, it must use the display list ID as the cache key.

This sort of approach seems like way more work.

@ColdPaleLight
Copy link
Member Author

@jonahwilliams @flar It seems that none of you like this proposal. Maybe we can move on to the previous proposal :)

@ColdPaleLight ColdPaleLight added the Work in progress (WIP) Not ready (yet) for review! label Apr 27, 2022
@flutter-dashboard
Copy link

This pull request executed golden file tests, but it has not been updated in a while (20+ days). Test results from Gold expire after as many days, so this pull request will need to be updated with a fresh commit in order to get results from Gold.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

platform-web Code specifically for the web engine Work in progress (WIP) Not ready (yet) for review!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Layer based raster caching is unstable for DisplayListLayer

3 participants