As per the [spec](https://www.w3.org/TR/png/#fcTL-chunk):
> The frame must be rendered within the region defined by x_offset, y_offset, width, and height. This region may not fall outside of the default image; thus x_offset plus width must not be greater than the [IHDR](https://www.w3.org/TR/png/#11IHDR) width; similarly y_offset plus height must not be greater than the [IHDR](https://www.w3.org/TR/png/#11IHDR) height.
While recently updating the DlColorSource sources I noticed some questionably implementation choices in the Color variant of the color sources.
I then realized that there was no public use of these classes (other than mostly their own unit tests) and so they should be deleted to focus on implementing the variants that are actually used by Flutter.
A new source code/header structure was introduced when the DlColorSource and DlImageFilter objects were migrated to Impeller geometry classes. Even though the DlColorFilter objects did not depend on Skia geometry objects, they need to be updated to the new source layout for consistency.
Reverts: flutter/engine#56606
Initiated by: LongCatIsLooong
Reason for reverting: https://github.com/flutter/flutter/issues/159456
Original PR Author: LongCatIsLooong
Reviewed By: {chunhtai, cbracken}
This change reverts the following previous change:
This PR adds basic FKA scrolling support: when the iOS focus (the focus state is maintained separately from the framework focus, see the previous PR) switches to an item in a scrollable container that is too close to the edge of the viewport, the container will scroll to make sure the next item is visible.
Previous PR for context: https://github.com/flutter/engine/pull/55964https://github.com/user-attachments/assets/84ae5153-f955-4d23-9901-ce942c0e98ac
### Why the UIScrollView subclass in the focus hierarchy
The iOS focus system does not provide an API that allows apps to notify it of focus highlight changes. So if we were to keep using the transforms sent by the framework as-is and not introducing any UIViews in the focus hierarchy, the focus highlight will be positioned at the wrong location after scrolling (via FKA or via framework). That does not seem to be part of the public API and the focus system seems to only know how to properly highlight focusable UIViews.
### Things that currently may not work
1. Nested scroll views (have not tried to verify)
The `UIScrollView`s are always subviews of the `FlutterView`. If there are nested scrollables the focus system may not be able to properly determine the focus hierarchy (in theory the iOS focus system should never depend on `UIView.parentView` but I haven't tried to verify that).
2. If the next item is too far below the bottom of the screen and there is a tab bar with focusable items, the focus will be transferred to tab bar instead of the next item in the list
Video demo (as you can see the scrolling is really finicky):
https://github.com/user-attachments/assets/51c2bfe4-d7b3-4614-aa49-4256214f8978
I've tried doing the same thing using a `UITableView` with similar configurations but it seems to have the same problem. I'll try to dig a bit deeper into this and see if there's a workaround.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This PR adds basic FKA scrolling support: when the iOS focus (the focus state is maintained separately from the framework focus, see the previous PR) switches to an item in a scrollable container that is too close to the edge of the viewport, the container will scroll to make sure the next item is visible.
Previous PR for context: https://github.com/flutter/engine/pull/55964https://github.com/user-attachments/assets/84ae5153-f955-4d23-9901-ce942c0e98ac
### Why the UIScrollView subclass in the focus hierarchy
The iOS focus system does not provide an API that allows apps to notify it of focus highlight changes. So if we were to keep using the transforms sent by the framework as-is and not introducing any UIViews in the focus hierarchy, the focus highlight will be positioned at the wrong location after scrolling (via FKA or via framework). That does not seem to be part of the public API and the focus system seems to only know how to properly highlight focusable UIViews.
### Things that currently may not work
1. Nested scroll views (have not tried to verify)
The `UIScrollView`s are always subviews of the `FlutterView`. If there are nested scrollables the focus system may not be able to properly determine the focus hierarchy (in theory the iOS focus system should never depend on `UIView.parentView` but I haven't tried to verify that).
2. If the next item is too far below the bottom of the screen and there is a tab bar with focusable items, the focus will be transferred to tab bar instead of the next item in the list
Video demo (as you can see the scrolling is really finicky):
https://github.com/user-attachments/assets/51c2bfe4-d7b3-4614-aa49-4256214f8978
I've tried doing the same thing using a `UITableView` with similar configurations but it seems to have the same problem. I'll try to dig a bit deeper into this and see if there's a workaround.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
The DlColorSource code uses Skia geometry classes for its internal computations. This PR switches those implementations to use the Impeller geometry classes for consistency and 3rd party header file independence.
The Info.plist override was missed earlier.
The main changes to the tests are due to the UI thread merge with the platform thread. The amendment to the "spawn" API are due to the fact that the assertions checked for the presence of GrDirectContext which will never exist with Impeller.
Unblocks https://github.com/flutter/engine/pull/56706
This PR introduces a `NativeAssetsManifest.json` next to the `AssetManifest.json` and `FontManifest.json`. This removes the need for embedding the native assets mapping inside the kernel file and will enable decoupling native assets building and bundling from the kernel compilation in flutter tools. This will then allow us to remove dry-run from the build hook protocol.
(It also means all isolate groups will have the same native assets. However, since Flutter does not support `Isolate.spawnUri` from kernel files anyways, this is not a regression.)
This manifest is parsed eagerly on startup by the engine in a manner similar to how the font manifest is parsed. The manifest contents need to be available in the callback for resolving assets, which does not have access to the engine. Therefore the parsed manifest is `NativeAssetsManager` stored in the `IsolateGroupData`. The engine passes it in on isolate group creation, and the FFI callbacks access it from the isolate group data.
Issue:
* https://github.com/flutter/flutter/issues/154425
Related PRs:
* https://dart-review.googlesource.com/c/sdk/+/388161
Follow up work:
* This PR does not yet remove the engine callbacks registered via the dart_api that rely on kernel embedding. If we were to do that in this PR, it would require a manual roll of the engine into flutter/flutter with the PR that switches flutter_tools to emit the native assets manifest instead of embedding in kernel, and a manual roll into g3 to switch emitting a manifest instead of embedding in kernel. A TODO is left in the code for those callbacks to be removed.
## Testing
Most of this PR cannot be tested in isolation. The code in this PR is heavily exercised in the follow up flutter_tools PR which creates the `NativeAssetsManifest.json` and removes the embedding of native assets in kernel files.
* This PR adds a unit test for parsing the JSON manifest.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
The DlImageFilter code uses Skia geometry classes for its internal computations. This PR switches those implementations to use the Impeller geometry classes for consistency and 3rd party header file independence.
Also updates the image_filter_test.dart expected color values for a blur unit test. The legacy blur algorithm would a) treat very small blur sigmas as the identity even though the effect was still perceptible and b) was very inaccurate for sigmas < 2. The unit test used a sigma of 1.0 so fell within the inaccurate range but the expected values appear to have been taken directly from the original Skia output. This updates them to match the output of the new algorithm (which is also more consistent between CPU and GPU).
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
For consistency with the Test.*Context classes for other backends, which live in their own implementation file with their own header, extract TestEGLContext to its own header and TU so that in cases where only a TestEGLContext is required (e.g. EmbedderTestBackingStoreProducerGL), we don't need to include all the various test GL surface classes as well.
GetEGLError is used by both TestEGLContext and the TestGLSurface classes, so moves to its own utils file.
No tests because this is a refactoring with no semantic changes, and the code itself is test code.
Issue: https://github.com/flutter/flutter/issues/158998
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
Enables the `-fobjc-arc` compiler flag for Objective-C and Objective-C++
translation units.
Eliminates the flutter_cflags_objc[c]_arc settings, since they're now
redundant.
All Obj-C/Obj-C++ code in our codebase has now been migrated to ARC.
Issue: https://github.com/flutter/flutter/issues/137801
The Metal context/surface code was only in the `flutter` namespace but should have been in `flutter::testing` for consistency with everything else in the `testing` directory.
Also squashes the declarations in the rest of that directory to match the style guide while I've got the macro still handy.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
Since Metal code frequently uses Objective-C types like id<MTLTexture>
etc. this migrates Metal translation units to Obj-C++. In particular,
this allows transitively including headers that include such types. This
in turn helps with refactoring `EmbedderTest`, `TestMetalContext`,
`TestMetalSurface` to avoid specifying `void*` types in headers and
manually refcounting via ARC bridge casts.
Reformats the source, since Objective-C files are linted to 100 columns
rather than the 80 column limit we impose on C++ files.
This change introduces no semantic changes.
Issue: https://github.com/flutter/flutter/issues/137801
Years ago, @chinmaygarde created TestMetalSurface and wrote a unit test
for it in 2866095b584bbdc7d9b24076fcb9d07716d673c9.
And some things that should not have been forgotten were lost. History
became legend. Legend became myth. And for four and a half years, the
test passed out of all knowledge. Until, when chance came, it ensnared a
new bearer. The test came to the creature @cbracken, who took it deep
into the tunnels of the GN build files. And there it consumed him. The
test brought to @cbracken unnatural long life. For 500 hours, it
poisoned his mind. And in the gloom of @cbracken's cave, it waited.
Darkness crept back into the forests of the world. Rumour grew of a
shadow in the East - whispers of a nameless fear. And the Test of Unit
perceived its time had now come.
`TestMetalContext` cannot include any Objective-C types in its header file since that header is included in pure C++ translation units. Previously, we declared these fields as `void*`, which then requires manual `__bridge_retained` and `__bridge_transfer` casts to perform the necessary retain/relase manipulation while opting the object in and out of ARC management.
Instead, we extract these to a struct in the implementation file and allow the fields to be managed by ARC. This is an interim measure consistent with the approach we've taken [elsewhere][1] until we implement the proper long-term solution.
The proper long-term solution is to refactor `EmbedderTest` (see: https://github.com/flutter/flutter/issues/157942) and other related code to split out backends into separate translation units, with the Metal backend code in Objective-C++ implementation files, which would then mean the headers could include Objective-C ivars.
No changes to tests, since this change introduces no behaviour changes.
Issue: https://github.com/flutter/flutter/issues/157942
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
Currently the most generalized form of the Impeller gradient shaders uses an SSBO to store the gradient information, but SSBO data is not supported on older platforms. To make the capability more general we introduce variants of the gradient shaders that uses uniform arrays which are more widely supported.
Copy-pasta docs:
```
/// Creates an image filter from a [FragmentShader].
///
/// The fragment shader provided here has additional requirements to be used
/// by the engine for filtering. The first uniform value must be a vec2, this
/// will be set by the engine to the size of the bound texture. There must
/// also be at least one sampler2D uniform, the first of which will be set by
/// the engine to contain the filter input.
///
/// For example, the following is a valid fragment shader that can be used
/// with this API. Note that the uniform names are not required to have any
/// particular value.
///
/// ```glsl
/// #include <flutter/runtime_effect.glsl>
///
/// uniform vec2 u_size;
/// uniform float u_time;
///
/// uniform sampler2D u_texture_input;
///
/// out vec4 frag_color;
///
/// void main() {
/// frag_color = texture(u_texture_input, FlutterFragCoord().xy / u_size) * u_time;
///
/// }
///
/// ```
///
/// This API is only supported when using the Impeller rendering engine. On
/// other backends a [UnsupportedError] will be thrown. This error can be
/// caught and used for feature detection.
```
Fixes https://github.com/jonahwilliams/flutter_shaders/issues/34
Fixes https://github.com/jonahwilliams/flutter_shaders/issues/26
Fixes https://github.com/flutter/flutter/issues/132099
Fixes https://github.com/flutter/flutter/issues/158275
We are now counting on the content context to keep the host buffer alive. the imgui overlay does not use a content context, so it has to manage the lifetime of the host buffer correctly, keeping it alive for as many frames as needed and destroying it in the correct order (before context destruction).
Ensure that all Objective-C code in the codebase is being built with the standard set of Flutter Objective-C compiler flags with ARC enabled.
Also bumps the cflags config up to the top of the first block within each target in which Objective-C sources appear, so that the location is consistent.
Migrates The following targets to ARC, which had been missed in previous passes since they didn't declare the standard Flutter Obj-C[++] cflags:
* `//flutter/fml:fml_unittests`
* `//flutter/impeller/golden_tests:metal_screenshot`
* `//flutter/impeller/playground:playground`
* `//flutter/impeller/backend/metal:metal`
* `//flutter/impeller/backend/metal:metal_unittests`
* `//shell/gpu:gpu_surface_metal_unittests`
* `//flutter/shell/platform/embedder:embedder_unittests`
This patch includes no semantic changes.
Issue: https://github.com/flutter/flutter/issues/137801
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
fml::scoped_nsobject and fml::scoped_nsprotocol classes are no longer
necessary now that the entire codebase has been migrated to ARC.
This also eliminates the fml_arc_unittests target which tests that code.
All references to that target in documentation, run_tests.py have been
removed. This target was used in various `et` build/query unit tests and
has been replaced with the fml_unittests target in those cases.
Issue: https://github.com/flutter/flutter/issues/137801
Users of this script typically expect that the normal output of the tests will be written to stdout. However, the logging.StreamHandler writes to stderr by default unless another stream is specified.
The framebuffer blend pipeline needs to support a dst_input_alpha parameter in order to implement the AbsorbOpacity flag.
Also, dst_input_alpha should only be applied to the alpha channel of the unpremultiplied destination color.
Fixes https://github.com/flutter/flutter/issues/157716
This migrates Flutter's TestMetalContext and TestMetalSurface to ARC.
Also migrates to using `sk_cfp::retain` (which retains the passed in pointer) rather than `sk_cfp::reset`, which only releases the previous pointer but doesn't retain the incoming pointer.
No changes to tests since no semantic changes.
Issue: https://github.com/flutter/flutter/issues/137801
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
`FlutterViewControllerTest testDrawLayer` created a callback which strongly referenced itself in its own body as part of an asynchronous recursive loop. The recursion was unnecessary and the test consistently passes, even if run on repeat > 100 times without it.
Now that there's only one call, eliminates the unnecessary local and inlines it into the `dispatch_after` call.
This was originally introduced in https://github.com/flutter/engine/pull/50072.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
- Align HostBuffer emplacements properly (fix Metal validation failures).
- Correctly set the pipeline sample size.
- Throw an error when attempting to bind `deviceTransient` textures.
Fixes https://github.com/flutter/flutter/issues/154935
Historically ImageFilter.blur supported setting a TileMode and had a default mode of `clamp`, but few developers actually set the value and the default was not appropriate for some common uses like as a backdrop filter where the clamp mode produces flashing when scrolling high frequency pixel content underneath a blurred title bar.
This PR removes the default tile mode instead allowing a null value as the default which will allow the engine to use an appropriate context-dependent default tile mode depending on the action being performed. Typically:
- decal for rendering operations and saveLayers and ImageFilterLayer
- clamp for image operations
- mirror for backdrop filters
The destination rect will then be updated to a mapping of the clipped source rect.
This matches the behavior of Skia's SkCanvas::drawImageRect.
Fixes https://github.com/flutter/flutter/issues/157167
Resolves https://github.com/flutter/flutter/issues/157336
`DartByteData` gets raw pointers into the Dart heap via `Dart_TypedDataAcquireData`. So it must be destructed before `AssociateWithDartWrapper` is called, which mutates the heap.
Re-enables failing test for Linux unopt.
Impeller geometry class analogous to SkRRect - soon to be the standard round rectangle class throughout most of the engine that doesn't talk directly to Skia.
More unit tests are being written, but this PR will enable developers to look at the API of the new class and comment as well as test its effect on any goldens (there should be none).