This enhances the overlay optimization by delaying combining pictures to get tighter bounds for the pictures that make up the scene, enabling more sophisticated optimization since we can determine if they intersect with platform views on a per-picture basis.
Fixes https://github.com/flutter/flutter/issues/149863
Fixes https://github.com/flutter/flutter/issues/155833
On a Macbook in Chrome in an example app with an infinite scrolling grid of platform views, this brings the ratio of dropped frames from 93% to 55% (roughly 4 fps to 30 fps).
This is a reland of https://github.com/flutter/engine/pull/54878 with a fix for scenes with pictures and shader masks that are eventually entirely clipped out. It also fixes a performance issue caused by making too many Canvases just to record the size of the picture elements in the scene.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This is an attempt to reland the overlay optimization for skwasm and fixing the golden diffs from the framework tests.
Original PR description:
This PR refactors the scene builder's logic in order to more aggressively merge flutter content and platform view content together. This essentially covers the case discussed in this flutter issue: https://github.com/flutter/flutter/issues/149863
This optimization ensures that each picture or platform view is applied to the lowest possible slice in the scene, which avoids the proliferation of redundant slices and overlays in the scene.
This enhances the overlay optimization by delaying combining pictures to get tighter bounds for the pictures that make up the scene, enabling more sophisticated optimization since we can determine if they intersect with platform views on a per-picture basis.
Fixes https://github.com/flutter/flutter/issues/149863
On a Macbook in Chrome in an example app with an infinite scrolling grid of platform views, this brings the ratio of dropped frames from 93% to 55% (roughly 4 fps to 30 fps).
This is a reland of https://github.com/flutter/engine/pull/54878 with a fix for scenes with pictures and shader masks that are eventually entirely clipped out.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
Reverts: flutter/engine#55402
Initiated by: chingjun
Reason for reverting: caused internal tests to fail.
See b/369740500 for more details.
Original PR Author: harryterkelsen
Reviewed By: {yjbanov}
This change reverts the following previous change:
This enhances the overlay optimization by delaying combining pictures to get tighter bounds for the pictures that make up the scene, enabling more sophisticated optimization since we can determine if they intersect with platform views on a per-picture basis.
Fixes https://github.com/flutter/flutter/issues/149863
On a Macbook in Chrome in an example app with an infinite scrolling grid of platform views, this brings the ratio of dropped frames from 93% to 55% (roughly 4 fps to 30 fps).
This is a reland of https://github.com/flutter/engine/pull/54878 with a fix for scenes with pictures that are eventually entirely clipped out.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This enhances the overlay optimization by delaying combining pictures to get tighter bounds for the pictures that make up the scene, enabling more sophisticated optimization since we can determine if they intersect with platform views on a per-picture basis.
Fixes https://github.com/flutter/flutter/issues/149863
On a Macbook in Chrome in an example app with an infinite scrolling grid of platform views, this brings the ratio of dropped frames from 93% to 55% (roughly 4 fps to 30 fps).
This is a reland of https://github.com/flutter/engine/pull/54878 with a fix for scenes with pictures that are eventually entirely clipped out.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This enhances the overlay optimization by delaying combining pictures to get tighter bounds for the pictures that make up the scene, enabling more sophisticated optimization since we can determine if they intersect with platform views on a per-picture basis.
Fixes https://github.com/flutter/flutter/issues/149863
On a Macbook in Chrome in an example app with an infinite scrolling grid of platform views, this brings the ratio of dropped frames from 93% to 55% (roughly 4 fps to 30 fps).
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
In certain situations, semantics elements get assigned `pointer-events: none` when they aren't supposed to.
One such situation is when a text field has a [decoration error text](https://api.flutter.dev/flutter/material/InputDecoration/errorText.html). The semantics node become a container, and we always set `pointer-events: none` on container nodes.
This PR introduces an `acceptsPointerEvents` getter on `SemanticRole` and `SemanticBehavior` to control when `pointer-events` should be `all` or `none`.
Fixes https://github.com/flutter/flutter/issues/141975
Reverts: flutter/engine#54949
Initiated by: eyebrowsoffire
Reason for reverting: Incorrect golden diffs on engine roll, see https://github.com/flutter/flutter/pull/155181
Original PR Author: eyebrowsoffire
Reviewed By: {harryterkelsen}
This change reverts the following previous change:
This PR refactors the scene builder's logic in order to more aggressively merge flutter content and platform view content together. This essentially covers the case discussed in this flutter issue: https://github.com/flutter/flutter/issues/149863
This optimization ensures that each picture or platform view is applied to the lowest possible slice in the scene, which avoids the proliferation of redundant slices and overlays in the scene.
This PR refactors the scene builder's logic in order to more aggressively merge flutter content and platform view content together. This essentially covers the case discussed in this flutter issue: https://github.com/flutter/flutter/issues/149863
This optimization ensures that each picture or platform view is applied to the lowest possible slice in the scene, which avoids the proliferation of redundant slices and overlays in the scene.
This removes usages of the deprecated top-level `instantiate` and
`invoke` methods and replaces it by method calls to the embedder
objects.
See [0] for the change that introduce this embedder API.
[0] https://dart-review.googlesource.com/c/sdk/+/383242/6
Relands https://github.com/flutter/engine/pull/54917. The change is the same as before, except now the native resources for `SkwasmColorFilter` and `SkwasmImageFilter` classes are no longer GC'd. Instead, we use manually managed native handles (vended and scoped by `withRawColorFilter` and `withRawImageFilter`). The bug in the previous PR was that filter objects were disposed with the paint while the framework continued holding onto them. When GC kicked the finalization registry, it attempted to double-free the filters.
The Dart analyzer will soon be changed so that if the `default` clause
of a `switch` statement is determined to be unreachable by the
exhaustiveness checker, a new warning of type
`unreachable_switch_default` will be issued. This parallels the behavior
of the existing `unreachable_switch_case` warning, which is issued
whenever a `case` clause of a `switch` statement is determined to be
unreachable.
Before adding the new warning to the analyzer, code in the engine needs
to first be updated to eliminate these unreachable `default` clauses, so
that the warning won't cause builds to break.
For more information, see
https://github.com/dart-lang/sdk/issues/54575.
In [some cases][1], text editing utilities re-focus the `<input />` element during a blur event. This causes an unusual sequence of `focusin` and `focusout` events, leading to the engine sending unintended events.
Consider the following HTML code:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="container">
<input type="" value="1" id="input1">
<input type="" value="2" id="input2">
<input type="" value="3" id="input3">
</div>
<script>
container.addEventListener('focusin', (ev) => {
console.log('focusin: focus was gained by', ev.target);
});
container.addEventListener('focusout', (ev) => {
console.log('focusout: focus is leaving', ev.target, 'and it will go to', ev.relatedTarget);
});
</script>
</body>
</html>
```
Clicking input1, then input2, then input3 produces the following console logs:
```
// Input1 is clicked
focusin: focus was gained by <input type value=â"1" id=â"input1">â
// Input2 is clicked
focusout: focus is leaving <input type value=â"1" id=â"input1">â and it will go to <input type value=â"2" id=â"input2">â
focusin: focus was gained by <input type value=â"2" id=â"input2">â
// Input3 is clicked
focusout: focus is leaving <input type value=â"2" id=â"input2">â and it will go to <input type value=â"3" id=â"input3">â
focusin: focus was gained by <input type value=â"3" id=â"input3">â
```
Now, let's add a blur handler that changes focus:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="container">
<input type="" value="1" id="input1">
<input type="" value="2" id="input2">
<input type="" value="3" id="input3">
</div>
<script>
container.addEventListener('focusin', (ev) => {
console.log('focusin: focus was gained by', ev.target);
});
container.addEventListener('focusout', (ev) => {
console.log('focusout: focus is leaving', ev.target, 'and it will go to', ev.relatedTarget);
});
input2.addEventListener('blur', (ev) => {
input2.focus();
});
</script>
</body>
</html>
```
The log sequence changes and gives the wrong impression that no dom element has focus:
```
// Input1 is clicked
focusin: focus was gained by <input type value=â"1" id=â"input1">â
// Input2 is clicked
focusout: focus is leaving <input type value=â"1" id=â"input1">â and it will go to <input type value=â"2" id=â"input2">â
focusin: focus was gained by <input type value=â"2" id=â"input2">â
// Input3 is clicked, but the handler kicks in and instead of the following line being a focusout, it results in a focusin call first.
focusin: focus was gained by <input type value=â"2" id=â"input2">â
focusout: focus is leaving <input type value=â"2" id=â"input2">â and it will go to null
```
In addition to that, during `focusout` processing, `activeElement` typically points to `<body />`. However, if an element is focused during a `blur` event, `activeElement` points to that focused element. Although, undocumented it can be verified with:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="container">
<input type="" value="1" id="input1">
<input type="" value="2" id="input2">
<input type="" value="3" id="input3">
</div>
<script>
container.addEventListener('focusin', (ev) => {
console.log('focusin: was gained by', ev.target);
});
container.addEventListener('focusout', (ev) => {
console.log('document.hasFocus()', document.hasFocus());
console.log('document.activeElement', document.activeElement);
console.log('focusout: focus is leaving', ev.target, 'and it will go to', ev.relatedTarget);
});
input2.addEventListener('blur', (ev) => {
input2.focus();
});
</script>
</body>
</html>
```
We leverage these behaviors to ignore `focusout` events when the document has focus but `activeElement` is not `<body />`.
https://github.com/flutter/flutter/issues/153022
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
Adds the `crossOrigin` property to the `<img>` tag used for decoding. This allows us to use cross-origin images in CanvasKit as if it were loaded from the same origin, as long as the CORS headers are properly set on the server hosting the image.
In the case where the image doesn't have proper CORS headers, this change causes an error to occur while attempting to decode, rather than later on in Skia when the image is converted into a texture. Hitting the cross-origin error later causes Skia to behave in undefined ways.
Progress towards https://github.com/flutter/flutter/issues/149843
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
Do not eagerly create an `SkPaint` object that's strongly referenced by `CkPaint`. Instead, when a `Canvas.draw*` is called, create a temporary `SkPaint` object, pass it to Skia, then immediately delete it. This way there are no persistent `SkPaint` handles lurking in the system that transitively hold onto expensive native resources.
Addresses the `Paint` issue in https://github.com/flutter/flutter/issues/153678 in CanvasKit
Spot checking some benchmarks. Here's the effect of this PR on `draw_rect_variable_paint`. It's a bit of a stress test as it creates 300K distinct `Paint` objects to render 600 pictures (a typical ratio does not normally exceed ten paints to one picture). Even so, the effect of creating an extra `SkPaint` on every `draw*` command does not look significant. However, removing a dependency on the GC for 300K objects looks like a good trade-off.
## Before
Allocation stats:
```
Paint Created: 300000
Paint Deleted: 300000
Paint Leaked: 300000
Picture Created: 600
Picture Deleted: 599
Picture Leaked: 599
```
Performance stats:
```
windowRenderDuration: (samples: 98 clean/2 outliers/100 measured/300 total)
| average: 4679.551020408163 μs
| outlier average: 5100 μs
| outlier/clean ratio: 1.0898481452084188x
| noise: 3.11%
sceneBuildDuration: (samples: 98 clean/2 outliers/100 measured/300 total)
| average: 4689.765306122449 μs
| outlier average: 5100 μs
| outlier/clean ratio: 1.087474461321549x
| noise: 3.19%
drawFrameDuration: (samples: 97 clean/3 outliers/100 measured/300 total)
| average: 8447.474226804125 μs
| outlier average: 9332.666666666666 μs
| outlier/clean ratio: 1.1047878236850721x
| noise: 3.52%
```
## After
Allocation stats:
```
Picture Created: 600
Picture Deleted: 599
Picture Leaked: 599
```
Performance stats:
```
windowRenderDuration: (samples: 97 clean/3 outliers/100 measured/300 total)
| average: 4780.40206185567 μs
| outlier average: 5133.666666666667 μs
| outlier/clean ratio: 1.0738985131877936x
| noise: 2.70%
sceneBuildDuration: (samples: 97 clean/3 outliers/100 measured/300 total)
| average: 4787.6082474226805 μs
| outlier average: 5133.666666666667 μs
| outlier/clean ratio: 1.0722821085936345x
| noise: 2.72%
drawFrameDuration: (samples: 97 clean/3 outliers/100 measured/300 total)
| average: 8243.309278350516 μs
| outlier average: 9033.333333333334 μs
| outlier/clean ratio: 1.0958382159768851x
| noise: 2.60%
```
Reverts: flutter/engine#54737
Initiated by: chingjun
Reason for reverting: Breaking internal tests. See b/363125155
Original PR Author: gaaclarke
Reviewed By: {matanlurey, jonahwilliams}
This change reverts the following previous change:
[This PR](https://github.com/flutter/engine/pull/54415) was reverted because it requires a manual roll into the framework.
issue: https://github.com/flutter/flutter/issues/127855
integration test: https://github.com/flutter/engine/pull/54415
This does the preliminary work for implementing wide gamut colors in the Flutter framework. Here are the following changes: 1) colors now specify a colorspace with which they are to be interpreted 1) colors now store their components as floats to accommodate bit depths more than 8
The storage of this Color class is weird with float/int storage but that is a temporary solution to support a smooth transition. Here is the plan for landing this:
1) Land this PR
1) Wait for it to roll into the Framework
1) Land https://github.com/flutter/flutter/pull/153938 which will make CupertinoDynamicColor implement Color
1) Land another engine PR that rips out the int storage: https://github.com/flutter/engine/pull/54714
Here are follow up PRs:
1) https://github.com/flutter/engine/pull/54473 - changes DlColor so the wide gamut colors are rendered
1) https://github.com/flutter/engine/pull/54567 - Hooks up these changes to take advantage of wide DlColor
1) https://github.com/flutter/flutter/pull/153319 - the integration test for the framework repo
There are some things that have been left as follow up PRs since they are technically breaking:
1) The math on `lerp` hasn't been updated to take advantage of the higher bit depth
1) `operator==` hasn't been updated to take advantage of the higher bit depth
1) `hashCode` hasn't been updated to take advantage of the higher bit depth
1) `alphaBlend` hasn't been updated to take advantage of the higher bit depth
1) `toString` hasn't been updated to take advantage of the higher bit depth
[This PR](https://github.com/flutter/engine/pull/54415) was reverted because it requires a manual roll into the framework.
issue: https://github.com/flutter/flutter/issues/127855
integration test: https://github.com/flutter/engine/pull/54415
This does the preliminary work for implementing wide gamut colors in the Flutter framework. Here are the following changes: 1) colors now specify a colorspace with which they are to be interpreted 1) colors now store their components as floats to accommodate bit depths more than 8
The storage of this Color class is weird with float/int storage but that is a temporary solution to support a smooth transition. Here is the plan for landing this:
1) Land this PR
1) Wait for it to roll into the Framework
1) Land https://github.com/flutter/flutter/pull/153938 which will make CupertinoDynamicColor implement Color
1) Land another engine PR that rips out the int storage: https://github.com/flutter/engine/pull/54714
Here are follow up PRs:
1) https://github.com/flutter/engine/pull/54473 - changes DlColor so the wide gamut colors are rendered
1) https://github.com/flutter/engine/pull/54567 - Hooks up these changes to take advantage of wide DlColor
1) https://github.com/flutter/flutter/pull/153319 - the integration test for the framework repo
There are some things that have been left as follow up PRs since they are technically breaking:
1) The math on `lerp` hasn't been updated to take advantage of the higher bit depth
1) `operator==` hasn't been updated to take advantage of the higher bit depth
1) `hashCode` hasn't been updated to take advantage of the higher bit depth
1) `alphaBlend` hasn't been updated to take advantage of the higher bit depth
1) `toString` hasn't been updated to take advantage of the higher bit depth
With [1] dart2wasm started using the new Wasm built-in string import
`wasm:js-string`.
With [2] dart2wasm started exporting `compile` and `compileStreaming`
from the generated JS runtime to compile dart2wasm-generated modules
with the `wasm:js-string` built-in, polyfilling it when not available.
Update Wasm compilation code in Flutter to use `compileStreaming` from
the JS runtime, enabling fast `jwasm:js-string` module when available.
[1]: 44c2e17600
[2]: 4cd6096da4
Closes https://github.com/flutter/flutter/issues/152636.
As of this PR, we no longer cherry-pick specific directories to run `dart analyze` on.
A few trailing errors across the repo had to be fixed in this PR.
Previously the "dialog" ARIA role was only set if the route or any of its descendants had the `namesRoute` flag. This PR sets the ARIA role unconditionally. Although it's always a good idea to have a label on the route, a missing label doesn't change the fact that the route is a route, so the ARIA role should still be set.
Fixes https://github.com/flutter/flutter/issues/153791
Remember the timestamp of _all_ `pointerup` events, not just those that were flushed. Clicks should be deduplicated after a `pointerup` even when not debouncing anything. This is because when not debouncing the engine already forwards all the pointer events to the framework, and sending click events on top only causes double-clicks.
Fixes https://github.com/flutter/flutter/issues/147050
The `type` attribute is needed for screen readers to tell the user whether the text field is a password or a plain text field.
Use `-webkit-text-security` for multi-line fields as a best effort (it's non-standard but is supported by all major browsers).
Fixes https://github.com/flutter/flutter/issues/153801
This removes the dependency on `dart:js` and allows that library to be removed from dart2wasm. Also updates `test` dependencies to work with the new `package:js` constraints.
This previously was basically assuming that two clip regions would be a union but instead it's actually an intersection. Also, for some reason I had forgotten to actually implement `boundingRect` for the rrect clip region. I changed this for a bit more clarity.
Enhances the overlay optimization by pushing new pictures to the earliest RenderCanvas they can go into. This improvement is made especially clear in the new test case I added to `embedded_views_test.dart`, with the previous algorithm we would have used an overlay for each platform view even though all of the pictures could go into the base canvas with no issue.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
Rename "dialog" to "route" to match the framework. The ARIA role "dialog" is an implementation detail, and it might change if a better implementation comes along. The semantic node itself implements the framework's "route" concept.