Skip to content

Support wide gamut colors in gradient_generator's CreateGradientTexture - #191980

Merged
auto-submit[bot] merged 3 commits into
flutter:masterfrom
b-luk:gradient-texture-wide-gamut
Sep 1, 2026
Merged

auto-submit[bot] merged 3 commits into
flutter:masterfrom
b-luk:gradient-texture-wide-gamut

Conversation

@b-luk

@b-luk b-luk commented Aug 28, 2026 •

Copy link
Copy Markdown
Contributor

This is a prerequisite to re-implementing #190874. This addresses the unsupported wide gamut issue which was originally present in that PR and which caused it to be reverted.

Related: #190401

Previously:

  • CreateGradientBuffer converts a gradient's colors and stops to an interpolated list of colors. This interpolated list of colors is converted to bytes with ToR8G8B8A8() and is returned in a GradientData.
  • The R8G8B8A8 GradientData is passed to CreateGradientTexture, which allocates a PixelFormat::kR8G8B8A8UNormInt texture.

Wide gamut colors can't be converted to R8G8B8A8, so they end up getting clamped.

Now:

  • CreateGradientBuffer converts a gradient's colors and stops to an interpolated list of colors (same as before). But now no conversion to bytes happens here. The interpolated list of colors is directly returned in a GradientData.
  • The Color-based GradientData is passed to CreateGradientTexture. CreateGradientTexture now handles the conversion to bytes. If there are wide gamut colors, it converts to kR32G32B32A32Float. Otherwise it does the old behavior of converting to PixelFormat::kR8G8B8A8UNormInt.

Pre-launch Checklist

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

If this change needs to override an active code freeze, provide a comment explaining why. The code freeze workflow can be overridden by code reviewers. See pinned issues for any active code freezes with guidance.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

@github-actions github-actions Bot added engine flutter/engine related. See also e: labels. e: impeller Impeller rendering backend issues and features requests labels Aug 28, 2026
@b-luk
b-luk force-pushed the gradient-texture-wide-gamut branch from 6591f24 to 5bef9f3 Compare August 31, 2026 17:04
@b-luk
b-luk force-pushed the gradient-texture-wide-gamut branch from 5bef9f3 to f77116f Compare August 31, 2026 17:17
@b-luk
b-luk marked this pull request as ready for review August 31, 2026 17:18
@b-luk

b-luk commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request updates Impeller's gradient generation to support wide-gamut colors by deferring color-to-byte conversion and storing raw Color objects in GradientData. CreateGradientTexture now dynamically selects between kR32G32B32A32Float and kR8G8B8A8UNormInt pixel formats based on whether any color is wide-gamut. Feedback suggests adding static_asserts to verify Color's layout and size, explicitly casting the texture size to avoid narrowing warnings, and simplifying the vector copy logic in CreateGradientBuffer.

Comment thread engine/src/flutter/impeller/entity/contents/gradient_generator.cc
Comment thread engine/src/flutter/impeller/entity/contents/gradient_generator.cc
Comment on lines 41 to 51
GradientData result = {
.colors = {},
};
data.color_bytes.reserve(texture_size * 4);
result.colors.reserve(texture_size);

if (texture_size == colors.size() &&
colors.size() <= kMaxGradientTextureSize) {
for (auto i = 0u; i < colors.size(); i++) {
AppendColor(colors[i], &data);
result.colors.push_back(colors[i]);
}
} else {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Since result.colors is now a std::vector<Color> and we are no longer converting colors to bytes during this step, we can directly assign colors to result.colors instead of manually looping and calling push_back. This also allows us to avoid calling reserve when the direct copy branch is taken.

  GradientData result;
  if (texture_size == colors.size() &&
      colors.size() <= kMaxGradientTextureSize) {
    result.colors = colors;
  } else {
    result.colors.reserve(texture_size);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request refactors gradient generation in Impeller to support wide-gamut gradients by updating GradientData to store a vector of Color objects instead of raw bytes. It dynamically selects the texture format (kR32G32B32A32Float for wide-gamut, kR8G8B8A8UNormInt otherwise) based on whether any color in the gradient is wide-gamut. Review feedback suggests adding static_assert guards for safe reinterpretation of Color data, avoiding implicit narrowing conversions when initializing ISize, using an epsilon tolerance in Color::IsWideGamut to prevent unnecessary promotion of standard sRGB gradients due to floating-point precision issues, and adding corresponding unit tests for boundary conditions.

Comment thread engine/src/flutter/impeller/entity/contents/gradient_generator.cc
Comment thread engine/src/flutter/impeller/entity/contents/gradient_generator.cc
Comment thread engine/src/flutter/impeller/geometry/color.h
Comment thread engine/src/flutter/impeller/geometry/geometry_unittests.cc
@b-luk b-luk added the CICD Run CI/CD label Aug 31, 2026
@b-luk
b-luk requested a review from gaaclarke August 31, 2026 18:43

@gaaclarke gaaclarke left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looking good. I just have a question about plumbing file formats or more efficient file formats and a note on EXPECT_ vs ASSERT_


std::vector<uint8_t> bytes;
if (is_wide_gamut) {
texture_descriptor.format = PixelFormat::kR32G32B32A32Float;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

32bit floats seems like overkill, how big are these? Can we use kR16G16B16A16Float? Or can we somehow plumb the framebuffer's pixel format here so we get the BGRA10XR?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

For the most common case of a 2-color gradient, the texture is 2x1, so the texture is 32 bytes with float32 (compared to 8 bytes with non-wide-gamut uint8s). Most gradients will not be much bigger than this, depending on the number of colors and the stop intervals of the gradient.

The worst case is when it uses kMaxGradientTextureSize of 1024, which happens for gradients with 3+ stops and where there is a very large ratio between the smallest and largest stop interval. I'm not expecting this to be a very common case, but with this worst case the texture is 1024x1 and will be 16KB with float32 (compared to 4KB with non-wide-gamut uint8s).

These sizes don't seem like they'd be a big deal to me, but I don't have a lot to base this on so let me know if it actually is a problem.

From asking Gemini about it, textures are sampled in the shader as float32s regardless of the platform's framebuffer pixel format. So using float32s here preserves full color precision and avoids extra conversions (both on the CPU and GPU) back and forth between different pixel formats.


auto gradient = CreateGradientBuffer(colors, stops);

ASSERT_EQ(gradient.colors.size(), 2u);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
ASSERT_EQ(gradient.colors.size(), 2u);
EXPECT_EQ(gradient.colors.size(), 2u);

Here and elsewhere.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done. Almost all of the rest of this file uses ASSERTs rather than EXPECTs. I don't want to change the entire file, so I just changed all the tests in the Gradient section.

@b-luk
b-luk requested a review from gaaclarke August 31, 2026 21:39

@gaaclarke gaaclarke left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm!

@b-luk b-luk added the autosubmit Merge PR when tree becomes green via auto submit App label Aug 31, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Sep 1, 2026
Merged via the queue into flutter:master with commit 1d790af Sep 1, 2026
24 of 25 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Sep 1, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Sep 1, 2026
flutter/flutter@c8c5e3b...0cbd1a4

2026-09-01 [email protected] Roll Skia from 6be7f8547c3c to 3911a1fe7f7a (1 revision) (flutter/flutter#192110)
2026-09-01 [email protected] Roll Fuchsia Linux SDK from EPzxifoyt36b5qiBy... to idslm9FikVLy2K_A-... (flutter/flutter#192104)
2026-09-01 [email protected] Roll Skia from 47df2ae3226c to 6be7f8547c3c (1 revision) (flutter/flutter#192103)
2026-09-01 [email protected] Roll Skia from e22ebf131e44 to 47df2ae3226c (4 revisions) (flutter/flutter#192099)
2026-09-01 [email protected] Roll Skia from 5489a16a5998 to e22ebf131e44 (5 revisions) (flutter/flutter#192093)
2026-09-01 [email protected] [flutter_tools] Safely handle broken symlinks and existing files during plugin symlink creation (flutter/flutter#191496)
2026-09-01 [email protected] Support wide gamut colors in gradient_generator's CreateGradientTexture (flutter/flutter#191980)
2026-09-01 [email protected] Clean up semantics code (flutter/flutter#191620)
2026-08-31 [email protected] Add website documentation item to PR pre-launch checklist (flutter/flutter#192080)
2026-08-31 [email protected] [windows] Fix null-deref in HostWindowPopup::UpdatePosition (Fixes #191478) (flutter/flutter#191479)
2026-08-31 [email protected] Removes deprecated ignoreSemantics parementers (flutter/flutter#191493)
2026-08-31 [email protected] Roll Dart SDK from b319095e317b to 9164def35347 (1 revision) (flutter/flutter#192073)
2026-08-31 [email protected] test: dynamic _tapOutside helper for TapRegion navigation tests (flutter/flutter#185397)
2026-08-31 [email protected] [Windows] fix: Remove quotes from compiler warning suppression (flutter/flutter#190873)
2026-08-31 [email protected] Migrate to listen package (flutter/flutter#189111)
2026-08-31 [email protected] Roll Skia from 15db98a90bbd to 5489a16a5998 (2 revisions) (flutter/flutter#192070)
2026-08-31 [email protected] Add regression test for plugin compileSdkExtension warning (flutter/flutter#191281)
2026-08-31 [email protected] Explicitly disable HCPP in platform view benchmarks and integration tests (flutter/flutter#191908)
2026-08-31 [email protected] Documentation and script for Gradle Distribution cache for CI (flutter/flutter#190323)
2026-08-31 [email protected] Roll Skia from 5549c93c9a1c to 15db98a90bbd (2 revisions) (flutter/flutter#192068)
2026-08-31 [email protected] Roll Packages from cd4cdd0 to d642322 (7 revisions) (flutter/flutter#192063)
2026-08-31 [email protected] Roll Dart SDK from 48f641e8b249 to b319095e317b (1 revision) (flutter/flutter#192061)
2026-08-31 [email protected] [tool] Migrate dev/tools from dart_skills_lint to skills_lint package (flutter/flutter#191997)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC [email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
@b-luk
b-luk deleted the gradient-texture-wide-gamut branch September 2, 2026 19:03
pull Bot pushed a commit to mikeyhodl/flutter that referenced this pull request Sep 3, 2026
flutter#192124)

This re-implements flutter#190874, after
landing:

flutter#191925 - Separated out some of
the fixes from the original PR
flutter#191980 - Add support for wide
gamut colors.

This re-implements the rest of the original PR. This is the same exact
code as the original PR, minus the changes that have already been merged
in flutter#191925.

Verified locally that the wide gamut test passes.

Related: flutter#190401

Original PR description:
----

Adds direct support for linear and radial gradient color sources to
UberSDF, enabling single-pass rendering of these gradients without the
multi-pass blending that is currently used.

- Adds a color_source_sampler input to UberSDF, which is used to sample
a texture representing the gradient color ramp for a linear or radial
gradient. This sampler may also be extended in the future for
image-based color sources, but that is outside the scope of this PR.
- Adds properties to UberSDFParameters and to UberSDF's FragInfo for
specifying gradient properties.
- Factors out code in `linear_gradient_fill.frag` and
`radial_gradient_fill.frag` that samples a texture to get a color for
linear and radial gradients. This logic is moved to functions in
`gradient.glsl`, to share with `uber_sdf.frag`.
- Updates `Canvas::AddRenderSDFEntityToCurrentPass` to fill in the
gradient texture and gradient related properties when
`paint.color_source` is a gradient supported by UberSDF.

This supports only linear and radial gradients. It does not support
conical and sweep gradients. According to Gemini, linear and radial
gradients make up more than 99% of gradient usage. Supporting conical
and sweep gradients would require additional complexity to UberSDF, so
it may not be worth it. We can revisit optimizing these other gradients
in the future if we see performance related to them in real world use
cases.

This change by itself speeds up gradient rendering significantly,
according to the results below. This can be further improved in a follow
up PR by adding caching for gradient textures, similar to
TextShadowCache in ContentContext.

Addresses flutter#190401.

Results from the demo app in
flutter#190401, run on my Windows VM.
Note that my Windows VM may not necessarily reflect real-world
performance, but these numbers still show significant improvements with
this PR. Also, my Windows VM reports a refresh rate of 500 hz, so almost
all frame render times are considered "over budget". So ignore the "over
budget" percentages and just look at the raw timing numbers.

before:

```
=== Windows linear-gradient comparison ===
mode=profile speed=1400px/s
Solid color | frames=953 fps=238.00 | ui p50/p95=0.669/1.231ms | raster p50/p90/p95/p99/max=4.131/5.154/5.519/6.192/6.830ms | raster_over_budget=949/953 (99.6%)
Linear gradient | frames=204 fps=50.75 | ui p50/p95=1.231/1.658ms | raster p50/p90/p95/p99/max=19.094/23.040/23.982/26.812/32.019ms | raster_over_budget=204/204 (100.0%)
================================================
```

after:
```
=== Windows linear-gradient comparison ===
mode=profile speed=1400px/s
Solid color | frames=833 fps=208.00 | ui p50/p95=0.635/1.033ms | raster p50/p90/p95/p99/max=4.752/5.570/5.732/6.134/7.504ms | raster_over_budget=833/833 (100.0%)
Linear gradient | frames=687 fps=171.50 | ui p50/p95=1.187/1.804ms | raster p50/p90/p95/p99/max=5.665/7.414/7.925/8.951/12.153ms | raster_over_budget=687/687 (100.0%)
================================================
```

Skia:
```
=== Windows linear-gradient comparison ===
mode=profile speed=1400px/s
Solid color | frames=1375 fps=343.50 | ui p50/p95=0.495/0.845ms | raster p50/p90/p95/p99/max=2.679/3.514/3.851/4.631/5.777ms | raster_over_budget=1160/1375 (84.4%)
Linear gradient | frames=1234 fps=308.25 | ui p50/p95=1.087/1.645ms | raster p50/p90/p95/p99/max=1.731/2.251/2.445/2.960/3.903ms | raster_over_budget=319/1234 (25.9%)
================================================
```

----

## Pre-launch Checklist

- [ ] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [ ] I read the [AI contribution guidelines] and understand my
responsibilities, or I am not using AI tools.
- [ ] 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 in-code documentation (doc comments with
`///`).
- [ ] If this PR introduces a new feature or capability, I created and
linked a website documentation issue or PR in [flutter/website] (or
verified none is needed).
- [ ] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [ ] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [ ] All existing and new tests are passing.

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

If this change needs to override an active code freeze, provide a
comment explaining why. The code freeze workflow can be overridden by
code reviewers. See pinned issues for any active code freezes with
guidance.

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[AI contribution guidelines]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[flutter/website]: https://github.com/flutter/website
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
victorsanni pushed a commit to victorsanni/packages that referenced this pull request Sep 9, 2026
…r#12712)

flutter/flutter@c8c5e3b...0cbd1a4

2026-09-01 [email protected] Roll Skia from 6be7f8547c3c to 3911a1fe7f7a (1 revision) (flutter/flutter#192110)
2026-09-01 [email protected] Roll Fuchsia Linux SDK from EPzxifoyt36b5qiBy... to idslm9FikVLy2K_A-... (flutter/flutter#192104)
2026-09-01 [email protected] Roll Skia from 47df2ae3226c to 6be7f8547c3c (1 revision) (flutter/flutter#192103)
2026-09-01 [email protected] Roll Skia from e22ebf131e44 to 47df2ae3226c (4 revisions) (flutter/flutter#192099)
2026-09-01 [email protected] Roll Skia from 5489a16a5998 to e22ebf131e44 (5 revisions) (flutter/flutter#192093)
2026-09-01 [email protected] [flutter_tools] Safely handle broken symlinks and existing files during plugin symlink creation (flutter/flutter#191496)
2026-09-01 [email protected] Support wide gamut colors in gradient_generator's CreateGradientTexture (flutter/flutter#191980)
2026-09-01 [email protected] Clean up semantics code (flutter/flutter#191620)
2026-08-31 [email protected] Add website documentation item to PR pre-launch checklist (flutter/flutter#192080)
2026-08-31 [email protected] [windows] Fix null-deref in HostWindowPopup::UpdatePosition (Fixes #191478) (flutter/flutter#191479)
2026-08-31 [email protected] Removes deprecated ignoreSemantics parementers (flutter/flutter#191493)
2026-08-31 [email protected] Roll Dart SDK from b319095e317b to 9164def35347 (1 revision) (flutter/flutter#192073)
2026-08-31 [email protected] test: dynamic _tapOutside helper for TapRegion navigation tests (flutter/flutter#185397)
2026-08-31 [email protected] [Windows] fix: Remove quotes from compiler warning suppression (flutter/flutter#190873)
2026-08-31 [email protected] Migrate to listen package (flutter/flutter#189111)
2026-08-31 [email protected] Roll Skia from 15db98a90bbd to 5489a16a5998 (2 revisions) (flutter/flutter#192070)
2026-08-31 [email protected] Add regression test for plugin compileSdkExtension warning (flutter/flutter#191281)
2026-08-31 [email protected] Explicitly disable HCPP in platform view benchmarks and integration tests (flutter/flutter#191908)
2026-08-31 [email protected] Documentation and script for Gradle Distribution cache for CI (flutter/flutter#190323)
2026-08-31 [email protected] Roll Skia from 5549c93c9a1c to 15db98a90bbd (2 revisions) (flutter/flutter#192068)
2026-08-31 [email protected] Roll Packages from cd4cdd0 to d642322 (7 revisions) (flutter/flutter#192063)
2026-08-31 [email protected] Roll Dart SDK from 48f641e8b249 to b319095e317b (1 revision) (flutter/flutter#192061)
2026-08-31 [email protected] [tool] Migrate dev/tools from dart_skills_lint to skills_lint package (flutter/flutter#191997)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC [email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
victorsanni pushed a commit to victorsanni/packages that referenced this pull request Sep 9, 2026
…r#12712)

flutter/flutter@c8c5e3b...0cbd1a4

2026-09-01 [email protected] Roll Skia from 6be7f8547c3c to 3911a1fe7f7a (1 revision) (flutter/flutter#192110)
2026-09-01 [email protected] Roll Fuchsia Linux SDK from EPzxifoyt36b5qiBy... to idslm9FikVLy2K_A-... (flutter/flutter#192104)
2026-09-01 [email protected] Roll Skia from 47df2ae3226c to 6be7f8547c3c (1 revision) (flutter/flutter#192103)
2026-09-01 [email protected] Roll Skia from e22ebf131e44 to 47df2ae3226c (4 revisions) (flutter/flutter#192099)
2026-09-01 [email protected] Roll Skia from 5489a16a5998 to e22ebf131e44 (5 revisions) (flutter/flutter#192093)
2026-09-01 [email protected] [flutter_tools] Safely handle broken symlinks and existing files during plugin symlink creation (flutter/flutter#191496)
2026-09-01 [email protected] Support wide gamut colors in gradient_generator's CreateGradientTexture (flutter/flutter#191980)
2026-09-01 [email protected] Clean up semantics code (flutter/flutter#191620)
2026-08-31 [email protected] Add website documentation item to PR pre-launch checklist (flutter/flutter#192080)
2026-08-31 [email protected] [windows] Fix null-deref in HostWindowPopup::UpdatePosition (Fixes #191478) (flutter/flutter#191479)
2026-08-31 [email protected] Removes deprecated ignoreSemantics parementers (flutter/flutter#191493)
2026-08-31 [email protected] Roll Dart SDK from b319095e317b to 9164def35347 (1 revision) (flutter/flutter#192073)
2026-08-31 [email protected] test: dynamic _tapOutside helper for TapRegion navigation tests (flutter/flutter#185397)
2026-08-31 [email protected] [Windows] fix: Remove quotes from compiler warning suppression (flutter/flutter#190873)
2026-08-31 [email protected] Migrate to listen package (flutter/flutter#189111)
2026-08-31 [email protected] Roll Skia from 15db98a90bbd to 5489a16a5998 (2 revisions) (flutter/flutter#192070)
2026-08-31 [email protected] Add regression test for plugin compileSdkExtension warning (flutter/flutter#191281)
2026-08-31 [email protected] Explicitly disable HCPP in platform view benchmarks and integration tests (flutter/flutter#191908)
2026-08-31 [email protected] Documentation and script for Gradle Distribution cache for CI (flutter/flutter#190323)
2026-08-31 [email protected] Roll Skia from 5549c93c9a1c to 15db98a90bbd (2 revisions) (flutter/flutter#192068)
2026-08-31 [email protected] Roll Packages from cd4cdd0 to d642322 (7 revisions) (flutter/flutter#192063)
2026-08-31 [email protected] Roll Dart SDK from 48f641e8b249 to b319095e317b (1 revision) (flutter/flutter#192061)
2026-08-31 [email protected] [tool] Migrate dev/tools from dart_skills_lint to skills_lint package (flutter/flutter#191997)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC [email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
RickyvdBerg added a commit to avio-os/avio-flutter that referenced this pull request Oct 2, 2026
…lutter#192124, flutter#192962)

UberSDF in this fork cannot shade a color source, so every antialiased
gradient rect, rrect, oval or circle (Avio's Shell and greeter run with
use_sdfs) was blended through a white SDF mask: two snapshots and a blend
target per draw, plus a deferred coverage pass in externalLinearBackdrop
mode. Upstream fixed this in the owning layer: fdb1d09 (flutter#192124) shades
linear and radial gradients inside UberSDF and 419f9dd (flutter#192962) adds the
storage-buffer variant used on Vulkan, so no ramp texture is made per draw.

Both upstream commits sit on intermediate UberSDF changes this fork does not
carry (uniform reordering, rect-path derivatives, stroke pixel size, which
would change other SDF output), and Avio's UberSDF carries patch 45's
coverage fields, so this is an adapted backport in one commit, not literal
cherry-picks:
- uber_sdf.frag is split into uber_sdf_common.glsl (shape SDFs, getColor,
  main) plus uber_sdf.frag (ramp texture) and uber_sdf_ssbo.frag (gradient
  stops in a storage buffer, the same math as the SSBO gradient shaders).
  Wherever the backend supports SSBOs (Vulkan), every UberSDF draw uses the
  SSBO variant, as upstream does.
- UberSDFParameters gains GradientParameters; UberSDFContents renders both
  variants from one FragInfo setup; color filters wrap on the GPU for a
  gradient, and a gradient is never a background color.
- Canvas::AddRenderSDFEntityToCurrentPass shades a linear or radial gradient
  whose local matrix (with the inverse shape transform) is a similarity.
  Conical and sweep gradients, images and runtime effects keep the masked
  kSrcIn path patch 52 slims. Patch 52's no-mask rect still comes first.
- A gradient shaded in UberSDF takes the coverage transfer in the shader;
  defer_coverage no longer includes the color source in that case.

Avio deltas against upstream (decision D3, accepted on the condition that
Avio's crisp look stays):
- Edges keep the old response: a gradient's SDF alpha uses the
  light-foreground gamma correction of the white mask it was blended through
  before, not the gradient's luma; the SSBO variant dithers like the SSBO
  gradient shaders, and like the masked composite it dithers the gradient
  color before coverage scales it, so a pixel the shape does not cover (the
  AA band's outside, the quad corners around a rounded shape) stays exactly
  transparent and srcOver adds nothing to what lies underneath. Upstream
  does not dither in UberSDF.
- Linear gradients also require a similarity matrix (upstream checks only
  affinity); mapping end points through a shear or non-uniform scale does not
  map the gradient's field.
- flutter#191925 and flutter#191980 are not brought in: the ramp-texture variant uses the
  fork's current GradientData, and Avio's SDF users take the SSBO variant.
- malioc.json is not updated.

Nothing else on the branch depends on this commit; its tests use patch
52's Playground::EnsureContextUsesSDFs. Reverting it alone restores the
masked path exactly.

Tests:
- UberSDFContentsTest.ApplyColorFilterWithGradient and
  AsBackgroundColorGradientReturnsNullopt (from upstream; red as compile
  failures on the base: GradientParameters did not exist).
- On every playground that renders with SDFs (Playground::
  EnsureContextUsesSDFs: Vulkan with SDFs enabled, which runs the
  storage-buffer variant Avio ships, and the OpenGL ES and Metal SDF
  backends, which run the ramp-texture variant; plain backends skip):
  AiksTest.SdfLinearGradientRectAllocatesNoOffscreen (expected red on the
  base: three offscreens), SdfRadialGradientCircleUnderNonUniformScale-
  AllocatesNoOffscreen, UnsupportedColorSourceStillBlends (a sweep gradient
  keeps exactly three offscreens), and SdfGradientEdgesMatchMaskedComposite:
  the pixel guard the user asked for. It renders rect, rounded rect, oval
  and circle with an opaque dark-to-light gradient and a translucent glass
  sheen, in platformDefault and externalLinearBackdrop, once shaded in
  UberSDF and once through the old masked composite (the same horizontal
  gradient with a y-scale local matrix, which leaves its field unchanged but
  routes it through the masked path). Every pixel, corners and antialiased
  edges included, must hold alpha within 2/255 and color within 2/255
  (ramp texture, no dither) or 5/255 (storage buffer: the composite dithered
  in its snapshot's grid, then quantized once more); every pixel the
  composite leaves fully transparent must stay exactly zero. Green by
  construction on the base (both renders take the masked path there); after
  this patch it fails if edges, corners, glass coverage or uncovered pixels
  drift.
- SdfGradientLeavesUncoveredQuadPixelsTransparent: the quad corners around a
  gradient circle are exactly zero in both coverage modes, opaque and glass.
  Red on the storage-buffer variant if the dither runs after coverage.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD e: impeller Impeller rendering backend issues and features requests engine flutter/engine related. See also e: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants