Skip to content

Improve non rect platform view rendering #182662

Merged
auto-submit[bot] merged 7 commits into
flutter:masterfrom
Hari-07:better-hybrid-blur
May 9, 2026
Merged

Improve non rect platform view rendering #182662
auto-submit[bot] merged 7 commits into
flutter:masterfrom
Hari-07:better-hybrid-blur

Conversation

@Hari-07

@Hari-07 Hari-07 commented Feb 20, 2026

Copy link
Copy Markdown
Contributor

Test setup:

return Stack(
      children: [
        Container(color: Colors.blue), // Flutter content behind
        const Text('Some random text'),
        ClipRRect(
          borderRadius: BorderRadius.circular(250),
          child: const PlatformViewWidget(), // platform view on top - red background with black text on it
        ),
        BackdropFilter(
          filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
          child: Center( 
            child: Container(
              height: 100,
              width: 100,
              color: Colors.blueAccent,
            ),
          ), // Flutter content infront of the blur
        )
      ],
    );

Before
image

After

Simulator Screenshot - iPhone 17 Pro - 2026-02-20 at 19 03 15

  • Currently the underlay is always clipped by platform view in a rectangular shape. This isn't correct because the platform view can have clips on it such as a rounded rect or a custom path even
  • The overlay was also always drawn in a rectangular shape
  • Blurred text can only be part of the underlay because there's no background information in overlay.
  • When a blured text was in the corner of a backdrop filter containing a platform view, the underlay which contains the blurred text got sliced away and overlay had unblurred text
  • This PR makes this flow clip aware and handles different clips correctly

Definitions:

  • Underlay: This is the flutter layer drawn below a platform view. When rendering we cut out holes in this layer for where the platform view will be rendered to save on compute
  • Overlay: This is the flutter layer drawn on top of the area occupied by the platform view.

List which issues are fixed by this PR. You must list at least one issue. An issue is not required if the PR fixes something trivial like a typo.
Fixes #150660

If you had to change anything in the flutter/tests repo, include a link to the migration guide as per the breaking change policy.

Pre-launch Checklist

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

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.

@Hari-07 Hari-07 requested a review from a team as a code owner February 20, 2026 13:36
@github-actions github-actions Bot added platform-ios iOS applications specifically engine flutter/engine related. See also e: labels. team-ios Owned by iOS platform team labels Feb 20, 2026
Comment on lines +146 to +173
TEST(ViewSlicerTest, PreservesUnderlayForSelectedViews) {
std::vector<int64_t> composition_order = {1};
std::unordered_map<int64_t, DlRect> view_rects = {
{1, DlRect::MakeLTRB(0, 0, 100, 100)}};

std::unordered_map<int64_t, std::unique_ptr<EmbedderViewSlice>>
baseline_slices;
AddSliceOfSize(baseline_slices, 1, DlRect::MakeLTRB(0, 0, 50, 50));
DisplayListBuilder baseline_builder(DlRect::MakeLTRB(0, 0, 100, 100));
auto baseline_overlays = SliceViews(&baseline_builder, composition_order,
baseline_slices, view_rects);
EXPECT_EQ(baseline_overlays.size(), 1u);
auto baseline_dl = baseline_builder.Build();
EXPECT_TRUE(ContainsClipDifferenceRect(baseline_dl));

std::unordered_map<int64_t, std::unique_ptr<EmbedderViewSlice>>
preserve_slices;
AddSliceOfSize(preserve_slices, 1, DlRect::MakeLTRB(0, 0, 50, 50));
std::unordered_set<int64_t> preserve_underlay_for_views = {1};
DisplayListBuilder preserve_builder(DlRect::MakeLTRB(0, 0, 100, 100));
auto preserve_overlays =
SliceViews(&preserve_builder, composition_order, preserve_slices,
view_rects, &preserve_underlay_for_views);
EXPECT_EQ(preserve_overlays.size(), 1u);
auto preserve_dl = preserve_builder.Build();
EXPECT_FALSE(ContainsClipDifferenceRect(preserve_dl));
}

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.

I was unsure how to test this, and got help from AI to write this test, just to be transparent

@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 addresses an issue where non-rectangular platform views were not rendering correctly by introducing clip-aware handling for different clip types. The changes involve modifying view_slicer.cc and view_slicer.h to accept a set of view IDs for which the underlay should be preserved, and updating FlutterPlatformViewsController.mm to identify and apply complex clips to the overlay canvas. A new unittest PreservesUnderlayForSelectedViews has been added to verify this new functionality. The changes improve the visual correctness of platform views with complex clips, especially in scenarios involving blurred text and backdrop filters.

#define FLUTTER_FLOW_VIEW_SLICER_H_

#include <unordered_map>
#include <unordered_set>

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

The addition of <unordered_set> is good for the new functionality. However, it should be placed in alphabetical order with the other includes for consistency and readability.

Suggested change
#include <unordered_set>
#include <unordered_map>
#include <unordered_set>

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.

@hellohuanlin have done this manually but I think this should happen through et format automatically if its an expectation

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.

i haven't tried et format, but ./ci/format.sh --fix should work

Comment thread engine/src/flutter/flow/view_slicer.cc Outdated
Comment thread engine/src/flutter/flow/view_slicer.cc
Comment thread engine/src/flutter/flow/view_slicer.h Outdated
@Hari-07 Hari-07 changed the title Make non rect platform views render correctly Improve non rect platform view rendering Feb 20, 2026
@gaaclarke

Copy link
Copy Markdown
Member

fyi @hellohuanlin (I think you've worked with this previously)

@hellohuanlin hellohuanlin self-requested a review February 23, 2026 18:55
@hellohuanlin

Copy link
Copy Markdown
Contributor

Hi @Hari-07, for ease of review & future reference, could you clarify (in PR description) what the blues and reds are in the screenshots? Also please address the gemini comments first? Thanks!

@Hari-07

Hari-07 commented Feb 24, 2026

Copy link
Copy Markdown
Contributor Author

Hi @Hari-07, for ease of review & future reference, could you clarify (in PR description) what the blues and reds are in the screenshots? Also please address the gemini comments first? Thanks!

Sure yeah I just added the code snippet, had forgotten that. Will address the gemini comments when I get some time next

@Hari-07 Hari-07 requested a review from a team as a code owner February 25, 2026 08:02
@github-actions github-actions Bot added platform-android Android applications specifically team-android Owned by Android platform team labels Feb 25, 2026
@Hari-07

Hari-07 commented Feb 25, 2026

Copy link
Copy Markdown
Contributor Author

The android changes are just to handle the signature change. I think its better to have explicit empty arg than have it be optional and implicit. Happy to revert that if any of you would prefer that

@Hari-07 Hari-07 force-pushed the better-hybrid-blur branch 2 times, most recently from eba02e3 to e3901aa Compare February 26, 2026 07:25
@jmagman

jmagman commented Feb 27, 2026

Copy link
Copy Markdown
Member

Hey @Hari-07, thanks for continuing to drill down on the platform view issues. Based on your previous contributions would you be interested in being sponsored for commit access? In addition to other rights, this means only one reviewer is required for your code, not two: https://github.com/flutter/flutter/blob/master/docs/contributing/Contributor-access.md
Feel free to DM me on Discord (I tried to DM you but the message bounced).

@Hari-07

Hari-07 commented Feb 27, 2026

Copy link
Copy Markdown
Contributor Author

Hey sure that sounds great , I tried messaging you on discord now too and it said that you only receive messages from friends, and it didn't let me send a friend request either. Not sure what's up there

@hellohuanlin

Copy link
Copy Markdown
Contributor

@Hari-07 hi, could you clarify in the PR description which screenshot is BEFORE and which is AFTER? and could you elaborate what "overlay" and "underlay" are in the PR description?

gmackall
gmackall previously approved these changes Mar 3, 2026

@gmackall gmackall 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.

from android triage, the android plumbing lgtm

@hellohuanlin

Copy link
Copy Markdown
Contributor

Hi, I am still a bit confused by the PR description.

Currently the underlay is always clipped by platform view in a rectangular shape. This isn't correct because the platform view can have clips on it such as a rounded rect or a custom path even

By underlay, are you referring to the blue background with "Some random text"? What's the incorrect result of "clipped in a rectangular shape"? The blue background widget with text seems to render correctly.

The overlay was also always drawn in a rectangular shape

By overlay do you mean the center blue box?

Blurred text can only be part of the underlay because there's no background information in overlay.

Which blurred text? The upper left corner or the center text?

When a blured text was in the corner of a backdrop filter containing a platform view, the underlay which contains the blurred text got sliced away and overlay had unblurred text

which blur text? Also in your code example, the backdrop filter does not contain a platform view, but rather it's a sibling of the platform view on a Stack widget.

@Hari-07

Hari-07 commented Mar 4, 2026

Copy link
Copy Markdown
Contributor Author

Perhaps its easier to understand with a textured background rather than text. On current main

Without Platform View
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Positioned.fill(
          child: Image.network(
            'https://images.unsplash.com/photo-1605106702842-01a887a31122?w=900&auto=format&fit=crop&q=60&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxzZWFyY2h8M3x8R2VvbWV0cnl8ZW58MHx8MHx8fDA%3D',
            fit: BoxFit.cover,
          ),
        ),
        BackdropFilter(
          filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
          child: Center(
            child: Container(height: 100, width: 100, color: Colors.blueAccent),
          ),
        ),
      ],
    );
  }
image
With Platform View
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Positioned.fill(
          child: Image.network(
            'https://images.unsplash.com/photo-1605106702842-01a887a31122?w=900&auto=format&fit=crop&q=60&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxzZWFyY2h8M3x8R2VvbWV0cnl8ZW58MHx8MHx8fDA%3D',
            fit: BoxFit.cover,
          ),
        ),
        Center(
          child: AspectRatio(
            aspectRatio: 1,
            child: ClipRRect(
              borderRadius: BorderRadius.circular(250),
              child: const PlatformViewWidget(), // platform view on top
            ),
          ),
        ),
        BackdropFilter(
          filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
          child: Center(
            child: Container(height: 100, width: 100, color: Colors.blueAccent),
          ),
        ),
      ],
    );
  }
image

In your code example, the backdrop filter does not contain a platform view, but rather it's a sibling of the platform view on a Stack widget.

By Blur containing platform view I meant - the Blur blurs a platform view. If it contained as in has a child that's a platform view the platform view wouldn't be itself getting blurred


Lets say these are the layers of the stack
image

When correctly rendered it should look like

image

Currently the portion of the UI that's rendered by flutter but within the Platform View Rect is unblurred


Current Rendering System image

Note that z-index is preserved

Updated Rendering System image

The primary change is that when preserve_underlay is true the background canvas (underlay) isn't clipped out

if (!preserve_underlay) {
        // Clip the background canvas, so it doesn't contain any of the pixels
        // drawn on the overlay layer.
        background_canvas->ClipRect(full_joined_rect, DlClipOp::kDifference);
      }

and that the overlay itself is clipped to the exact path of the platform view rather than the rect occupied by the platform view

if (preserveUnderlayForViews.find(viewId) != preserveUnderlayForViews.end()) {
      ApplyComplexClipToOverlayCanvas(overlayCanvas, self.currentCompositionParams[viewId]);
    }

With the updated engine code the same code with platform view looks like

image

@Hari-07 Hari-07 force-pushed the better-hybrid-blur branch from e3901aa to 0f0db8a Compare March 4, 2026 06:40

@hellohuanlin hellohuanlin 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.

Thank you for providing the detailed!

I wonder have you thought about blurring the overlay, rather than clipping off part of the overlay and show the underlay?

I ask this because this PR doesn't cover the case where an overlay region that needs to be blurred sits inside the platform view's shape. For example, if there's a Flutter widget (green box below) inside the platform view's shape (red circle), but outside of the backdrop filter, it also needs to be blurred.

Image

#define FLUTTER_FLOW_VIEW_SLICER_H_

#include <unordered_map>
#include <unordered_set>

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.

i haven't tried et format, but ./ci/format.sh --fix should work

@Hari-07

Hari-07 commented Mar 6, 2026

Copy link
Copy Markdown
Contributor Author

I did actually think about that case.

There are a couple issues. What I showed above is actually a slight simplification. Cos actually the background image isn't part of the overlay at all. The overlay only contains objects drawn in front of the platform view.

In the current scenario when overlay is transparent in the region that's inside the rect but outside platform view (4 corners) and we clip the underlay as well, its actually a different layer that's drawn even behind the underlay that shows up.

So blurring the overlay wouldn't solve the bug that I originally pointed out.
So unless we sample behind the platform view, then propogate that to the overlay this wouldn't work
Which seems more expensive than just rendering the area occupied by the platform view twice


The issue you pointed out is separete

To solve that I did think about blurring the overlay as well. As far I can say, that's a one line change here to not skip on applying the blur (not sure what other side effects that may have) but there are some issues with that

  • There's no background to sample so if the thing being blurred is translucent it wont be correct

  • Another problem is the edge of the underlay and overlay, which is both non platform view, would have a visible artifact at the border because of how blur works. The edges on either side has no information about the other side.

I used a different image to hopefully make it clearer

image

@hellohuanlin

hellohuanlin commented Mar 17, 2026

Copy link
Copy Markdown
Contributor

Thanks for providing new details. This will be on the top of my review stack. Will try to get to it this week.

@Hari-07

Hari-07 commented Mar 17, 2026

Copy link
Copy Markdown
Contributor Author

For blurring over the platform and solving the edge at once, I did find a solution that I posted about here. But that's a wider change I need to think about more

@hellohuanlin

Copy link
Copy Markdown
Contributor

There are a couple issues. What I showed above is actually a slight simplification. Cos actually the background image isn't part of the overlay at all. The overlay only contains objects drawn in front of the platform view.

Could you provide a similar diagram to what was provided? I will be very helpful for future reference. Thanks!

@Hari-07

Hari-07 commented May 8, 2026

Copy link
Copy Markdown
Contributor Author

Hey @hellohuanlin , have made the nit changes and marked as ready again. Apologies for the delays

@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 modifies the SliceViews function to allow preserving the underlay for specific platform views, primarily to support non-rectangular clips on iOS. It includes updates to the view slicer, unit tests, and the iOS platform views controller. Review feedback highlights a compilation error caused by a function name mismatch in FlutterPlatformViewsController.mm and recommends consistent naming for the new SliceViews parameter across the header and implementation files.

Comment thread engine/src/flutter/flow/view_slicer.cc
Comment thread engine/src/flutter/flow/view_slicer.cc

@hellohuanlin hellohuanlin 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.

LGTM. Thanks for addressing feedbacks. 🚢

This was referenced May 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD engine flutter/engine related. See also e: labels. platform-android Android applications specifically platform-ios iOS applications specifically team-android Owned by Android platform team team-ios Owned by iOS platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Blur doesn't apply properly when a platform view gets rounded

7 participants