Skip to content

Conversation

@dnfield
Copy link
Contributor

@dnfield dnfield commented Sep 1, 2021

fixes #89255
fixes #71008

Now, instead of dropping the opacity layer when it is either disabled or the value is opaque, it uses an OffsetLayer instead. This avoids some of the memory regression from #83145, because the engine special cases OpacityLayers to always raster cache them, but does not do quite the same with OffsetLayers.

I did see some regression on mean/median on the internal benchmark, but overall the values are still within the range of the change without this PR.

/cc @xster

@flutter-dashboard flutter-dashboard bot added f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels. labels Sep 1, 2021
@google-cla google-cla bot added the cla: yes label Sep 1, 2021
@skia-gold
Copy link

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

@skia-gold
Copy link

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

@skia-gold
Copy link

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

Copy link
Member

Choose a reason for hiding this comment

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

ahve -> have

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ahh thanks, fixed. I also noticed in the setter above I was accessing the gettr instead of the instance var. Changed that too.

Copy link
Member

Choose a reason for hiding this comment

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

Without this patch, this test can pass also, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The container gets rendered in the wrong location without this patch

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Err, sorry - without this change, there'd be no OpacityLayer, the PictureLayer would be the firstChild of rootLayer.

Copy link
Member

Choose a reason for hiding this comment

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

It passes with the latest master branch.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ahh you are right. This would need to test that the add to scene does the right thing. But the golden test does that without getting into such implementation details. I'll remove this test.

Copy link
Member

Choose a reason for hiding this comment

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

It isn't bad to remain this ^^

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree, it's not bad to keep this test, even if it passes without this change and has coverage in a golden file test. I think it's never bad to have another test. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Left it in :)

Copy link
Contributor

@Piinks Piinks left a comment

Choose a reason for hiding this comment

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

LGTM with typo @xu-baolin spotted

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree, it's not bad to keep this test, even if it passes without this change and has coverage in a golden file test. I think it's never bad to have another test. :)

@skia-gold
Copy link

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

@skia-gold
Copy link

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

@fluttergithubbot
Copy link
Contributor

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

  • The status or check suite Linux flutter_plugins has failed. Please fix the issues identified (or deflake) before re-applying this label.

@flutter-dashboard
Copy link

Golden file changes have been found for this pull request. Click here to view and triage (e.g. because this is an intentional change).

If you are still iterating on this change and are not ready to resolve the images on the Flutter Gold dashboard, consider marking this PR as a draft pull request above. You will still be able to view image results on the dashboard, commenting will be silenced, and the check will not try to resolve itself until marked ready for review.

For more guidance, visit Writing a golden file test for package:flutter.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

Changes reported for pull request #89264 at sha 3e660a04c72f5a86e7e5c3c0f4afb10e828cfa86

@flutter-dashboard flutter-dashboard bot added the will affect goldens Changes to golden files label Sep 10, 2021
@fluttergithubbot
Copy link
Contributor

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

  • The status or check suite Google testing has failed. Please fix the issues identified (or deflake) before re-applying this label.

@dnfield
Copy link
Contributor Author

dnfield commented Sep 10, 2021

This changes some internal goldens in an expected manner, since there's no longer the pixel snapping going on at the end of an opacity animation. /cc @renyou @angjieli - this looks like it affected about 170 golden files internally in a smoke test. I assume it will be more in a full TGP.

@zanderso
Copy link
Member

/cc @flar

Copy link
Contributor

@flar flar left a comment

Choose a reason for hiding this comment

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

Some concerns over mixing of state correctness between methods and whether opacity/alpha values are always range protected vs. using inequality in tests, but otherwise no blockers...

Copy link
Contributor

Choose a reason for hiding this comment

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

The type of the engineLayer is specific to the implementation of the addToScene method. Rather than null it here where the reason for the nullification isn't immediately obvious, deal with the wrong type down in addToScene.

Basically in addToScene, only pass along the oldLayer if it is of the right type and it will get replaced naturally.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because addToScene is on a hot path, and will require type checks every time that hot path gets hit, whereas we know what the type will be based ont he value of the opacity.

Copy link
Contributor

Choose a reason for hiding this comment

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

A single is is going to completely derail our performance?
Compared to the improved maintainability by not having multiple functions have to deal with an implementation detail of one of them?

addToScene has to do an as anyway which implicitly includes an is, but throws if it fails rather than just substituting null which is the logical reaction to the type being wrong. Note that with the is you likely don't even need the as because the runtime is smart enough to elide them.
You are already paying the price of type checking the parameter in addToScene, why complicate it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So I figured I don't have a benchmark to back this up and I can just make this change. However, there's another complication here. What I really want is it to be an error to call addToScene with an incorrect engineLayer, because you cannot mutate the engineLayer during addToScene, and if we got called addToScene without nulling out the no-longer-needed engineLayer, we've made a mistake that wastes memory.

I'm happy to update the documentation on this if it's not already updated, but I think the asserts and mutations are correct this way, and we'd risk recurisvely calling addToScene if we start trying to mutate the engineLayer there.

Copy link
Contributor

Choose a reason for hiding this comment

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

How is "this object wants to decide on the fly which type of engine layer to use when it adds to the scene" compatible with "addToScene is not allowed to mutate the engineLayer and we will make that an error"?

Philosophically those two concepts are at odds with each other. You can't justify one without pointing out that the other is or has an invalid assumption.

Adding code to prevent a conflict between them is a workaround and points out that the design decisions had some cases they didn't really address.

You are basically nulling out the field to destroy the evidence that the engine layer is actually dynamic here.

And if there is a reason for it to be dynamic here, then what is the value of a globally enforced assertion that it isn't.

Copy link
Contributor

Choose a reason for hiding this comment

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

(None of this is blocking, btw, I'm just a little skeptical over the design constraints that led to this implementation...)

Copy link
Contributor

Choose a reason for hiding this comment

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

While we're here, should this be > 0? Some places that check alpha use an inequality and other places use equality tests (see RenderAnimatedOpacityMixin below).

Copy link
Contributor

Choose a reason for hiding this comment

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

I see that there are some asserts in here, but not sure if they protect every value test or not.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fair, I'll fix this. Previously we couldn't use that because 255 was also special cased :)

Copy link
Contributor

Choose a reason for hiding this comment

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

Here we use inequality for alpha test, other places use equality testing. Perhaps all tests on alpha should use tests that are safe in the presence of out-of-range values like this?

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, there are range asserts sprinkled around, but it is hard to tell from a PR diff if they are consistently protecting every line of code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We use the following code from dart:ui to calculate alpha

  static int getAlphaFromOpacity(double opacity) {
    assert(opacity != null);
    return (opacity.clamp(0.0, 1.0) * 255).round();
  }

It's guarnateed to not go out of bounds.

Copy link
Contributor

Choose a reason for hiding this comment

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

Inter-method dependencies for correctness are weaker than just having this method deal with the wrong layer type that it knows happens because it is the method that causes it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The asserts in here guard against this getting broken, and there is test coverage that would trigger them should it break. I did this becuase it's on a hot path.

Copy link
Contributor

Choose a reason for hiding this comment

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

What is the value of subclassing OffsetLayer if we push our own?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Eliminates duplicated code with regard to setting the transform, and both layers provide an offset property.

Users of this API don't really deal directly with scene builder - but in some of my explorations around trying to optimize layer usage, it can be helpful to know whether a layer has an offset or not.

Copy link
Contributor

Choose a reason for hiding this comment

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

No range assert here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That should be addressed in a separate PR.

@dnfield
Copy link
Contributor Author

dnfield commented Sep 10, 2021

@flar - I'm not quite clear if you want to discuss the checks further. For some of the range asserts, I think we should just file a new bug and address it separately in case this gets reverted. They're not a bad idea, but there's not a great reason IMHO to include them here where they were already absent.

I'd prefer to avoid the type checks in addToScene simply because that code path gets hit very frequently, including after the alpha has settled on whatever value the animation ends/stops/pauses at.

@skia-gold
Copy link

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

@skia-gold
Copy link

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

@flar
Copy link
Contributor

flar commented Sep 11, 2021

@flar - I'm not quite clear if you want to discuss the checks further. For some of the range asserts, I think we should just file a new bug and address it separately in case this gets reverted. They're not a bad idea, but there's not a great reason IMHO to include them here where they were already absent.

Handling that separately sounds good.

I'd prefer to avoid the type checks in addToScene simply because that code path gets hit very frequently, including after the alpha has settled on whatever value the animation ends/stops/pauses at.

None of that is a blocking comment, but I'm still not clear why you think that it is saving anything for frequently hit code. The code already has an as operator which is (A is B) ? A : throw and that has the same cost as (A is B) ? A : null with the language not requiring the as in that case.

(I'd love to see the language have an as? operator that was literally "or null" rather than "or throw".)

@dnfield
Copy link
Contributor Author

dnfield commented Sep 11, 2021

The performance concerns are really secondary. The real problem is that if you got all the way to addToScene with the wrong kind of engineLayer, you made a mistake along the way and potentially retained an entire layer tree (and any images it had) longer than necessary. Once you know the alpha is changing the layer should let the engine know to release resources.

@dnfield
Copy link
Contributor Author

dnfield commented Sep 13, 2021

Landing this on red because the scuba changes are expected.

@flar - happy to discuss further and see if we can continue to improve on this, but again my main concern is around not holding native resources any longer than absolutely necessary.

@dnfield dnfield merged commit 0d0f7a4 into flutter:master Sep 13, 2021
@dnfield dnfield deleted the opacity_fix branch September 13, 2021 04:17
dnfield added a commit that referenced this pull request Sep 13, 2021
dnfield added a commit that referenced this pull request Sep 13, 2021
@dnfield dnfield mentioned this pull request Sep 13, 2021
guidezpl added a commit that referenced this pull request Sep 15, 2021
* add `semanticsLabel` to `SelectableText`

* remove unused vars

* Squashed commit of the following:

commit 3e687a9
Author: engine-flutter-autoroll <[email protected]>
Date:   Tue Sep 14 17:42:05 2021 -0400

    Roll Plugins from 4a98e23 to b85edeb (2 revisions) (#90083)

commit ad936b4
Author: Christopher Fujino <[email protected]>
Date:   Tue Sep 14 14:39:17 2021 -0700

    [flutter_conductor] Support initial stable release version (#89775)

commit ff5dd54
Author: Ian Hickson <[email protected]>
Date:   Tue Sep 14 13:02:04 2021 -0700

    Mention the ToS on our README (#89765)

commit 8587b60
Author: Kate Lovett <[email protected]>
Date:   Tue Sep 14 14:53:33 2021 -0500

    Update local gold api (#90072)

commit 7d368dc
Author: Justin McCandless <[email protected]>
Date:   Tue Sep 14 12:39:19 2021 -0700

    InteractiveViewer with a child of zero size (#90012)

    Asserts that the InteractiveViewer child can't have zero size.

commit 2b4ef18
Author: Akira Aratani <[email protected]>
Date:   Wed Sep 15 03:30:50 2021 +0900

    Fix document of the switch. (#89641)

commit a2cd16b
Author: Christopher Fujino <[email protected]>
Date:   Tue Sep 14 11:22:02 2021 -0700

    use test logger, which does not allow colors (#90010)

commit 0f0613c
Author: Varun Sharma <[email protected]>
Date:   Tue Sep 14 11:17:03 2021 -0700

    Add specific permissions to .github/workflows/lock.yaml (#89820)

commit 2866f79
Author: Jason Simmons <[email protected]>
Date:   Tue Sep 14 10:46:35 2021 -0700

    Initialize all bindings before starting the text_editing_action_target test suite (#90067)

    Fixes #90057

commit b889915
Author: Michael Thomsen <[email protected]>
Date:   Tue Sep 14 14:08:36 2021 +0200

    Change min Dart SDK constraint to track actual version (#88743)

commit 3b7adb9
Author: godofredoc <[email protected]>
Date:   Mon Sep 13 21:32:04 2021 -0700

    Lock only issues. (#90023)

commit 528f77d
Author: Dan Field <[email protected]>
Date:   Mon Sep 13 19:10:15 2021 -0700

    Opacity fix (#90017)

    * Make sure Opacity widgets/layers do not drop the offset

commit 2470f63
Author: engine-flutter-autoroll <[email protected]>
Date:   Mon Sep 13 22:07:02 2021 -0400

    4a98e23 [flutter_plugin_tools] Make no unit tests fatal for iOS/macOS (flutter/plugins#4341) (#90016)

commit a01e473
Author: stuartmorgan <[email protected]>
Date:   Mon Sep 13 20:57:05 2021 -0400

    Re-enable plugin analysis test (#89856)

commit cdad35f
Author: Aneesh Rao <[email protected]>
Date:   Tue Sep 14 05:17:04 2021 +0530

    Fix path in example (#84707)

commit 576aab0
Author: Christopher Fujino <[email protected]>
Date:   Mon Sep 13 15:47:03 2021 -0700

    add analysis_options.yaml to dev/conductor (#90005)

commit fad5e4c
Author: Jason Simmons <[email protected]>
Date:   Mon Sep 13 13:37:07 2021 -0700

    Remove a redundant test case in the flutter_tools create_test (#89872)

commit 738430c
Author: Darren Austin <[email protected]>
Date:   Mon Sep 13 13:33:48 2021 -0700

    Revert "Removed default page transitions for desktop and web platforms. (#82596)" (#89997)

    This reverts commit 43e3197

commit 9db9256
Author: Dan Field <[email protected]>
Date:   Mon Sep 13 13:15:19 2021 -0700

    Revert "Make sure Opacity widgets/layers do not drop the offset (#89264)" (#89999)

    This reverts commit 0d0f7a4.

commit 00f78cf
Author: keyonghan <[email protected]>
Date:   Mon Sep 13 13:04:01 2021 -0700

    renew cirrus key (#89988)

commit 826da7f
Author: engine-flutter-autoroll <[email protected]>
Date:   Mon Sep 13 15:52:03 2021 -0400

    cfc8a20 renew cirrus key (flutter/plugins#4340) (#89996)

commit cd112e5
Author: Anna Gringauze <[email protected]>
Date:   Mon Sep 13 12:13:42 2021 -0700

    Update all packages (#89797)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels. will affect goldens Changes to golden files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OpacityLayer should be a subclass of OffsetLayer RenderAnimatedOpacityMixin causes child pixel snapping when fully opaque

7 participants