Sitelet https://web.archive.org/web/20220108230851/https://github.com/flutter/flutter/pull/95977
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LayerLink can temporary allow multiple leaders #95977

Merged
merged 2 commits into from Jan 8, 2022

Conversation

@chunhtai
Copy link
Contributor

@chunhtai chunhtai commented Dec 30, 2021 •

fixes #95974

If a child layer is moved to a new container layer in the same frame. the assert will throw if the new container is painted before the old container is painted. This pr fixes it so that the pipelineowner resets all the dirty container layer before any of them is painted

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, including Features we expect every widget to implement.
  • I signed the CLA.
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is test-exempt.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

packages/flutter/lib/src/rendering/object.dart Outdated Show resolved Hide resolved
packages/flutter/lib/src/rendering/object.dart Outdated Show resolved Hide resolved
packages/flutter/lib/src/rendering/object.dart Outdated Show resolved Hide resolved
packages/flutter/lib/src/rendering/object.dart Outdated Show resolved Hide resolved
packages/flutter/lib/src/rendering/object.dart Outdated Show resolved Hide resolved
LayerLink? layerLink;

@override
bool isRepaintBoundary = true;
Copy link
Member

@goderbauer goderbauer Jan 4, 2022

Choose a reason for hiding this comment

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

Just to double check: There isn't a problem if we are not a repaint boundary?

Copy link
Contributor Author

@chunhtai chunhtai Jan 4, 2022

Choose a reason for hiding this comment

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

It will still be a problem.

The reason i made it a repaint boundary is for easy testing. If it is not a repaint boundary, the markNeedsPaint will go through the ancestor chain to find the nearest repaint boundary and markNeedsPaint on it. That means I would have to create a parent repaint boundary in the test anyway.

Copy link
Member

@goderbauer goderbauer Jan 4, 2022

Choose a reason for hiding this comment

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

But that case is also fixed by this fix, right?

Copy link
Contributor Author

@chunhtai chunhtai Jan 4, 2022

Choose a reason for hiding this comment

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

Yes, In the layer tree, the non-repaint boundary renderobject does not contributing additional node, so there is no difference between layer added by non-repaint boundary renderobject and layer added by the nearest repaint boundary.

packages/flutter/lib/src/rendering/object.dart Outdated Show resolved Hide resolved
// layer may be appended to a new parent layer before it is removed from
// the old parent layer.
dirtyNodes.sort((RenderObject a, RenderObject b) => b.depth - a.depth);
for (final RenderObject node in dirtyNodes) {
Copy link
Member

@goderbauer goderbauer Jan 4, 2022

Choose a reason for hiding this comment

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

Since this is performance critical code: We are not doing any extra work now, right? We are just doing the reset upfront instead of later?

Copy link
Contributor Author

@chunhtai chunhtai Jan 4, 2022

Choose a reason for hiding this comment

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

yes, but it becomes two for-loops instead of one. Not sure whether there will be any impact on perf. If this is not acceptable, I will then have to do something similar to globalkey duplication that temporary allows child to be attached to two parents and adds a postframecallback to make sure the previous parent give up the child.

This will be more complicated than the global key cases though, since it involves detaching/attaching logic.

@skia-gold
Copy link

@skia-gold skia-gold commented Jan 4, 2022

Gold has detected about 8 new digest(s) on patchset 3.
View them at https://flutter-gold.skia.org/cl/github/95977

@chunhtai chunhtai requested a review from goderbauer Jan 4, 2022
@chunhtai
Copy link
Contributor Author

@chunhtai chunhtai commented Jan 4, 2022

@goderbauer
Copy link
Member

@goderbauer goderbauer commented Jan 5, 2022

Why does this change goldens? Is that expected?

@chunhtai
Copy link
Contributor Author

@chunhtai chunhtai commented Jan 6, 2022

@goderbauer that is previous commit, which broke a lot of tests, the latest commit does not have golden change

@chunhtai chunhtai changed the title Reset composited layer before any of them is repainted LayerLink can temporary allow multiple leaders Jan 6, 2022
@chunhtai
Copy link
Contributor Author

@chunhtai chunhtai commented Jan 6, 2022

Set<LeaderLayer>? _debugPreviousLeaders;
bool _debugLeaderCheckScheduled = false;

/// schedule the check as post frame callback to make sure the
Copy link
Member

@goderbauer goderbauer Jan 6, 2022

Choose a reason for hiding this comment

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

schedule -> Schedule

packages/flutter/lib/src/rendering/layer.dart Show resolved Hide resolved
assert(link._leader != this);
assert((){
if (link._leader != null) {
link._debugPreviousLeaders ??= <LeaderLayer>{};
link._debugPreviousLeaders!.add(link._leader!);
link._debugScheduleLeadersCleanUpCheck();
}
return true;
}());
Copy link
Member

@goderbauer goderbauer Jan 6, 2022

Choose a reason for hiding this comment

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

I would move all of this into a _registerLeader method on LeaderLink to keep this a little cleaner here. This is all impl. detail of leaderLink.

assert(link._leader != null);
if (link._leader == this) {
link._leader = null;
} else {
assert((){
if (link._leader != this) {
return link._debugPreviousLeaders!.remove(this);
}
return true;
}());
}
Copy link
Member

@goderbauer goderbauer Jan 6, 2022

Choose a reason for hiding this comment

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

Same with this.

@@ -2197,7 +2247,10 @@ class LeaderLayer extends ContainerLayer {
if (_link == value) {
return;
}
_link._leader = null;
if (attached) {
Copy link
Contributor Author

@chunhtai chunhtai Jan 6, 2022

Choose a reason for hiding this comment

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

wrote a test switching layer link of an attached leader layer should not crash for this change

@chunhtai
Copy link
Contributor Author

@chunhtai chunhtai commented Jan 6, 2022

@goderbauer PTAL, I also fixed another corner case.

Copy link
Member

@goderbauer goderbauer left a comment

LGTM

@fluttergithubbot
Copy link
Contributor

@fluttergithubbot fluttergithubbot commented Jan 8, 2022

This pull request is not suitable for automatic merging in its current state.

  • This commit is not mergeable and has conflicts. Please rebase your PR and fix all the conflicts.

@fluttergithubbot fluttergithubbot merged commit e17a185 into flutter:master Jan 8, 2022
65 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

4 participants