Fixes: https://github.com/flutter/flutter/issues/128159
In diagnosing test failures for https://github.com/flutter/engine/pull/42330 we discovered that the DisplayList code was not always backwards compatible with computing the bounds of inverted rectangles (where left > right or top > bottom). Historically such rectangles were always rendered as if they were sorted (i.e. `SkRect::makeSorted()`), but we computed bounds as if the bounds only mattered if the supplied rectangle was ordered. So, we would sometimes render a rectangle for which we mis-computed the bounds.
This would rarely surface in the current code as most rendered rectangles would pass through `SkMatrix::mapRect()` which implicitly orders the rectangle as it transforms it, but any attributes applied to the bounds before that method may have been applied "in the wrong direction" - such as:
- stroke width padding
- mask blur padding
- image filter padding
Fixes https://github.com/flutter/flutter/issues/116070
Fixes https://github.com/flutter/flutter/issues/126202
Introduces `DlRegion` class which implements subset of `SkRegion`
required to get non-overlapping rectangles from region.
The implementation is different and faster than `SkRegion` for this
particular use-case (`display_list_region_benchmarks`):
Edit: Updated benchmark to latest revision and natively (initial run
went through rosetta)
```
----------------------------------------------------------------------------
Benchmark Time CPU Iterations
----------------------------------------------------------------------------
BM_RegionBenchmarkDlRegion/Tiny 616 us 616 us 908
BM_RegionBenchmarkSkRegion/Tiny 70559 us 70557 us 10
BM_RegionBenchmarkDlRegion/Small 1315 us 1314 us 537
BM_RegionBenchmarkSkRegion/Small 121736 us 121717 us 6
BM_RegionBenchmarkDlRegion/Medium 1079 us 1079 us 650
BM_RegionBenchmarkSkRegion/Medium 22039 us 22035 us 32
BM_RegionBenchmarkDlRegion/Large 399 us 399 us 1763
BM_RegionBenchmarkSkRegion/Large 1510 us 1510 us 466
```
## Pre-launch Checklist
- [X] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [X] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [X] I read and followed the [Flutter Style Guide] and the [C++,
Objective-C, Java style guides].
- [X] I listed at least one issue that this PR fixes in the description
above.
- [X] 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.
- [X] I updated/added relevant documentation (doc comments with `///`).
- [X] I signed the [CLA].
- [X] All existing and new tests are passing.
If you need help, consider asking for advice on the #hackers-new channel
on [Discord].
<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#overview
[Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene
[Flutter Style Guide]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo
[C++, Objective-C, Java style guides]:
https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
[testing the engine]:
https://github.com/flutter/flutter/wiki/Testing-the-engine
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes
[Discord]: https://github.com/flutter/flutter/wiki/Chat
The original PR caused some golden test failures down the line, likely due to bad analysis of when the combined BlendMode and color would result in a NOP situation.
This PR adds tests that go through every BlandMode and pair it with a variety of colors and Color/ImageFilters to verify that the operations are only omitted when they actually produce no change in the output. It also checks the validity of the "modifies_transparent_black" property of DisplayLists which can be used in place of the current CanvasSpy/DlOpSpy classes.
The description from the [previous PR](https://github.com/flutter/engine/pull/41463) updated with the new name of the DL property:
---------------------------------
This optimization avoids recording unnecessary render operations that will not affect the output and also eliminates the need for "draw detection" mechanisms like `DlOpSpy` and `CanvasSpy` by remembering if any non-transparent operations were included. The `DlOpSpy` unit tests were updated to check if the results from that object match the new `DisplayList::modifies_transparent_black()` method.
Fixes https://github.com/flutter/flutter/issues/125338
In addition, this change will unblock some other Issues:
- https://github.com/flutter/flutter/issues/125318
- https://github.com/flutter/flutter/issues/125403
Part of an ongoing set of efforts to address https://github.com/flutter/flutter/issues/106448
Move the checkerboard layer unit tests onto the DisplayList version of the paint contexts and fix some bugs in the reusability of the DisplayListBuilder that this migration uncovered.
This optimization avoids recording unnecessary render operations that will not affect the output and also eliminates the need for "draw detection" mechanisms like `DlOpSpy` and `CanvasSpy` by remembering if any non-transparent operations were included. The `DlOpSpy` unit tests were updated to check if the results from that object match the new `DisplayList::affects_transparent_surface()` method.
Fixes https://github.com/flutter/flutter/issues/125338
In addition, this change will unblock some other Issues:
- https://github.com/flutter/flutter/issues/125318
- https://github.com/flutter/flutter/issues/125403
Part of an ongoing set of efforts to address https://github.com/flutter/flutter/issues/106448
MockTexture now executes a call on the supplied DlCanvas object rather than creating its own list of MockCanvas-style draw calls. The TextureLayer tests now no longer use MockCanvas.
Part of an ongoing set of efforts to address https://github.com/flutter/flutter/issues/106448
The layer unittests have been using a MockCanvas class to record the painting of trees of layers and then testing for the expected output.
A while back a similar mechanism was created to compare DisplayList output and to print out a human-friendly version of the differences found, but it was only used in a few tests written at the time it was created and a few since then.
This is the first in a series of PRs that will move all the rest of the unit tests onto the new DL comparison mechanism, starting with the layer types that just do basic drawing. Some of the remaining layers will require creating new hooks in, for instance, the Texture registry, the performance overlay TextBlob generation, etc.
These tests break under Skia's new behaviors when evaluating the bounds of ill-defined filtering operations such as ColorFilters that affect even transparent pixels.
The Flutter engine is currently building with a backwards compatibility flag which we should be able to remove with the new versions of these tests.
Switching the calls to dispatch into an Impeller Dispatcher to use a cull rect to enable pre-culling of the out-of-bounds ops.
This change showed an improvement of around 2x on the rendering performance of the non-intersecting platform view benchmark, but that was measured without the recent changes to the destructive blend modes in Impeller renderer.
With this PR we no longer need to hold DisplayLists in GPUObject wrappers and they can be disposed instantly instead of queueing on the Unref thread.
This will definitely be a win for Impeller as none of the objects used in a frame now require queueing, but the performance impact on apps running on top of skia is less clear if they depend on a lot of images inside their DisplayLists that still need to be queued to be freed. After getting further in the work, it looks like only decoded images need to use the protected DlImage wrappers and most of those should survive many frames before they are disposed. That should hopefully leave very few unrefs happening per frame.
~There are 3 unit tests in `shell_unittests.cc` and `embedder_metal_unittests.mm` that are now GSKIP'd as they now invoke code that needs a fully initialized UIDartState in order to protect their images. I will look into fixing the tests and/or making the code they invoke provide protection without relying on UIDartState.~ (This looks to be fixed in the latest commit by simply not creating DlImageGPUs all over the source base and simply catching only those that end up in UI data structures. There is actually existing code in one of the modules that feeds ui.Image with an answer to wrap the image in a DlImageGPU if it has a skia image anyway, so most of these additional uses of DlImageGPU that were having trouble getting the Skia unref queue just didn't need it anyway.)
* add support to run dl_canvas_unittests on GPU surfaces (off by default)
* empty commit to trigger build
* conditionally include platform-specific surface provider headers
* ignore DL test files during license checks
* typo
* add dependencies to rendertests to hopefully build on Windows
* remove benchmarking deps from dl_rendertests
* more changes to get Windows rendertests to link
* add --enable-gl synonym and prevent non-SW surface provider dest on Windows
* fix gn formatting
* review feedback
* collect DL indices in RTree for clip culling
* fix bounds in unit test and minor opt in Dispatch
* normalize inline matrix objects and minor fixes to unit test
* remove over-eager DCHECK and improve R-Tree comments
* formatting
* include vector for Windows
* method rename and distribute child nodes more evenly
* add R-Tree specific unit tests and debug checks
* add comments about geometry to R-Tree unit tests and adjust spacing
* licenses
* licenses attempt 2
* fix potential overflow with uint32_t
* aggressively const DisplayList fields and methods
* add implementation comments per review feedback