From 5c27bcf0720f82bbfdcb4e0d9923a406efc69f40 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Wed, 5 Jul 2023 11:14:14 -0700 Subject: [PATCH] [iOS] Avoid crash when backdrop filter is null for PlatformViews (flutter/engine#43150) During certain partial repaint logic, the backdrop filter layer is present but the filter itself is null. We need to account for it when deciding whether to add such filter to the mutator stack. Fixes https://github.com/flutter/flutter/issues/127095 [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style --- .../flow/layers/backdrop_filter_layer.cc | 2 +- .../Scenarios.xcodeproj/project.pbxproj | 4 ++ .../ios/Scenarios/Scenarios/AppDelegate.m | 2 + .../ScenariosUITests/GoldenTestManager.m | 2 + .../ScenariosUITests/PlatformViewUITests.m | 18 +++++ ...one SE (3rd generation)_16.2_simulator.png | Bin 0 -> 20583 bytes .../scenario_app/lib/src/platform_view.dart | 64 +++++++++++++++++- .../scenario_app/lib/src/scenarios.dart | 1 + 8 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 engine/src/flutter/testing/scenario_app/ios/Scenarios/ScenariosUITests/golden_platform_view_with_negative_backdrop_filter_iPhone SE (3rd generation)_16.2_simulator.png diff --git a/engine/src/flutter/flow/layers/backdrop_filter_layer.cc b/engine/src/flutter/flow/layers/backdrop_filter_layer.cc index fd3c656146..44c3fca4a6 100644 --- a/engine/src/flutter/flow/layers/backdrop_filter_layer.cc +++ b/engine/src/flutter/flow/layers/backdrop_filter_layer.cc @@ -42,7 +42,7 @@ void BackdropFilterLayer::Diff(DiffContext* context, const Layer* old_layer) { void BackdropFilterLayer::Preroll(PrerollContext* context) { Layer::AutoPrerollSaveLayerState save = Layer::AutoPrerollSaveLayerState::Create(context, true, bool(filter_)); - if (context->view_embedder != nullptr) { + if (filter_ && context->view_embedder != nullptr) { context->view_embedder->PushFilterToVisitedPlatformViews( filter_, context->state_stack.device_cull_rect()); } diff --git a/engine/src/flutter/testing/scenario_app/ios/Scenarios/Scenarios.xcodeproj/project.pbxproj b/engine/src/flutter/testing/scenario_app/ios/Scenarios/Scenarios.xcodeproj/project.pbxproj index 4e69202318..81e3520794 100644 --- a/engine/src/flutter/testing/scenario_app/ios/Scenarios/Scenarios.xcodeproj/project.pbxproj +++ b/engine/src/flutter/testing/scenario_app/ios/Scenarios/Scenarios.xcodeproj/project.pbxproj @@ -62,6 +62,7 @@ 6860CE272A01B2FF00B68EC5 /* golden_two_platform_view_clip_path_iPhone SE (3rd generation)_16.2_simulator.png in Resources */ = {isa = PBXBuildFile; fileRef = 6860CE242A01B2FF00B68EC5 /* golden_two_platform_view_clip_path_iPhone SE (3rd generation)_16.2_simulator.png */; }; 68A5B63423EB71D300BDBCDB /* PlatformViewGestureRecognizerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 68A5B63323EB71D300BDBCDB /* PlatformViewGestureRecognizerTests.m */; }; 68D4017D2564859300ECD91A /* ContinuousTexture.m in Sources */ = {isa = PBXBuildFile; fileRef = 68D4017C2564859300ECD91A /* ContinuousTexture.m */; }; + 68D93AEE2A46097E0054AB6D /* golden_platform_view_with_negative_backdrop_filter_iPhone SE (3rd generation)_16.2_simulator.png in Resources */ = {isa = PBXBuildFile; fileRef = 68D93AED2A46097E0054AB6D /* golden_platform_view_with_negative_backdrop_filter_iPhone SE (3rd generation)_16.2_simulator.png */; }; F26F15B8268B6B5600EC54D3 /* iPadGestureTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F26F15B7268B6B5500EC54D3 /* iPadGestureTests.m */; }; /* End PBXBuildFile section */ @@ -183,6 +184,7 @@ 68A5B63323EB71D300BDBCDB /* PlatformViewGestureRecognizerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PlatformViewGestureRecognizerTests.m; sourceTree = ""; }; 68D4017B2564859300ECD91A /* ContinuousTexture.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ContinuousTexture.h; sourceTree = ""; }; 68D4017C2564859300ECD91A /* ContinuousTexture.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ContinuousTexture.m; sourceTree = ""; }; + 68D93AED2A46097E0054AB6D /* golden_platform_view_with_negative_backdrop_filter_iPhone SE (3rd generation)_16.2_simulator.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "golden_platform_view_with_negative_backdrop_filter_iPhone SE (3rd generation)_16.2_simulator.png"; sourceTree = ""; }; F26F15B7268B6B5500EC54D3 /* iPadGestureTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = iPadGestureTests.m; sourceTree = ""; }; F72114B628EF99F500184A2D /* Info_Impeller.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info_Impeller.plist; sourceTree = ""; }; /* End PBXFileReference section */ @@ -308,6 +310,7 @@ F7B464DC2759D02B00079189 /* Goldens */ = { isa = PBXGroup; children = ( + 68D93AED2A46097E0054AB6D /* golden_platform_view_with_negative_backdrop_filter_iPhone SE (3rd generation)_16.2_simulator.png */, 6860CE242A01B2FF00B68EC5 /* golden_two_platform_view_clip_path_iPhone SE (3rd generation)_16.2_simulator.png */, 6860CE232A01B2FF00B68EC5 /* golden_two_platform_view_clip_rect_iPhone SE (3rd generation)_16.2_simulator.png */, 6860CE222A01B2FF00B68EC5 /* golden_two_platform_view_clip_rrect_iPhone SE (3rd generation)_16.2_simulator.png */, @@ -477,6 +480,7 @@ 684FFF8629F9C10700281002 /* golden_bogus_font_text_iPhone SE (3rd generation)_16.2_simulator.png in Resources */, 684FFF7E29F9C10700281002 /* golden_platform_view_opacity_iPhone SE (3rd generation)_16.2_simulator.png in Resources */, 684FFF8729F9C10700281002 /* golden_platform_view_multiple_iPhone SE (3rd generation)_16.2_simulator.png in Resources */, + 68D93AEE2A46097E0054AB6D /* golden_platform_view_with_negative_backdrop_filter_iPhone SE (3rd generation)_16.2_simulator.png in Resources */, 684FFF8D29F9C10700281002 /* golden_platform_view_large_cliprrect_iPhone SE (3rd generation)_16.2_simulator.png in Resources */, 684FFF8329F9C10700281002 /* golden_platform_view_transform_iPhone SE (3rd generation)_16.2_simulator.png in Resources */, 684FFF8B29F9C10700281002 /* golden_platform_view_clippath_iPhone SE (3rd generation)_16.2_simulator.png in Resources */, diff --git a/engine/src/flutter/testing/scenario_app/ios/Scenarios/Scenarios/AppDelegate.m b/engine/src/flutter/testing/scenario_app/ios/Scenarios/Scenarios/AppDelegate.m index a41ef85866..d938a89537 100644 --- a/engine/src/flutter/testing/scenario_app/ios/Scenarios/Scenarios/AppDelegate.m +++ b/engine/src/flutter/testing/scenario_app/ios/Scenarios/Scenarios/AppDelegate.m @@ -55,6 +55,8 @@ @"--platform-view-with-other-backdrop-filter" : @"platform_view_with_other_backdrop_filter", @"--two-platform-views-with-other-backdrop-filter" : @"two_platform_views_with_other_backdrop_filter", + @"--platform-view-with-negative-backdrop-filter" : + @"platform_view_with_negative_backdrop_filter", @"--platform-view-rotate" : @"platform_view_rotate", @"--non-full-screen-flutter-view-platform-view" : @"non_full_screen_flutter_view_platform_view", @"--gesture-reject-after-touches-ended" : @"platform_view_gesture_reject_after_touches_ended", diff --git a/engine/src/flutter/testing/scenario_app/ios/Scenarios/ScenariosUITests/GoldenTestManager.m b/engine/src/flutter/testing/scenario_app/ios/Scenarios/ScenariosUITests/GoldenTestManager.m index 3bcff69684..78bda2122b 100644 --- a/engine/src/flutter/testing/scenario_app/ios/Scenarios/ScenariosUITests/GoldenTestManager.m +++ b/engine/src/flutter/testing/scenario_app/ios/Scenarios/ScenariosUITests/GoldenTestManager.m @@ -41,6 +41,8 @@ NSDictionary* launchArgsMap; @"--platform-view-with-other-backdrop-filter" : @"platform_view_with_other_backdrop_filter", @"--two-platform-views-with-other-backdrop-filter" : @"two_platform_views_with_other_backdrop_filter", + @"--platform-view-with-negative-backdrop-filter" : + @"platform_view_with_negative_backdrop_filter", @"--platform-view-rotate" : @"platform_view_rotate", @"--non-full-screen-flutter-view-platform-view" : @"non_full_screen_flutter_view_platform_view", diff --git a/engine/src/flutter/testing/scenario_app/ios/Scenarios/ScenariosUITests/PlatformViewUITests.m b/engine/src/flutter/testing/scenario_app/ios/Scenarios/ScenariosUITests/PlatformViewUITests.m index 511700b9ac..03984f27fd 100644 --- a/engine/src/flutter/testing/scenario_app/ios/Scenarios/ScenariosUITests/PlatformViewUITests.m +++ b/engine/src/flutter/testing/scenario_app/ios/Scenarios/ScenariosUITests/PlatformViewUITests.m @@ -380,6 +380,24 @@ static const NSInteger kSecondsToWaitForPlatformView = 30; @end +@interface PlatformViewWithNegativeOtherBackDropFilterTests : GoldenPlatformViewTests + +@end + +@implementation PlatformViewWithNegativeOtherBackDropFilterTests + +- (instancetype)initWithInvocation:(NSInvocation*)invocation { + GoldenTestManager* manager = [[GoldenTestManager alloc] + initWithLaunchArg:@"--platform-view-with-negative-backdrop-filter"]; + return [super initWithManager:manager invocation:invocation]; +} + +- (void)testPlatformView { + [self checkPlatformViewGolden]; +} + +@end + @interface PlatformViewRotation : GoldenPlatformViewTests @end diff --git a/engine/src/flutter/testing/scenario_app/ios/Scenarios/ScenariosUITests/golden_platform_view_with_negative_backdrop_filter_iPhone SE (3rd generation)_16.2_simulator.png b/engine/src/flutter/testing/scenario_app/ios/Scenarios/ScenariosUITests/golden_platform_view_with_negative_backdrop_filter_iPhone SE (3rd generation)_16.2_simulator.png new file mode 100644 index 0000000000000000000000000000000000000000..bc5162bebdae39fe8d2c50e818cf3e6f5cb94bc7 GIT binary patch literal 20583 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 Z|HMPp)i!H;-hmGJ^K|udS?83{1OS;6Hqih8 literal 0 HcmV?d00001 diff --git a/engine/src/flutter/testing/scenario_app/lib/src/platform_view.dart b/engine/src/flutter/testing/scenario_app/lib/src/platform_view.dart index 9e3c559130..7c15465dc9 100644 --- a/engine/src/flutter/testing/scenario_app/lib/src/platform_view.dart +++ b/engine/src/flutter/testing/scenario_app/lib/src/platform_view.dart @@ -1443,8 +1443,6 @@ class PlatformViewWithOtherBackDropFilter extends PlatformViewScenario { /// A simple platform view for testing backDropFilter with a platform view in the scene. /// /// The stack would look like: picture 1 -> pv1 -> picture 2 -> filter -> pv2 - > picture 3. -/// Because backdrop filter on platform views has not been implemented(see: https://github.com/flutter/flutter/issues/43902), -/// the result will not including a filtered pv1. class TwoPlatformViewsWithOtherBackDropFilter extends Scenario with _BasePlatformViewScenarioMixin { /// Constructs the scenario. @@ -1533,6 +1531,68 @@ class TwoPlatformViewsWithOtherBackDropFilter extends Scenario } } +/// A simple platform view for testing backDropFilter with a platform view in the scene. +/// +/// The backdrop filter sigma value is negative, which tries to reproduce a crash, see: +/// https://github.com/flutter/flutter/issues/127095 +class PlatformViewWithNegativeBackDropFilter extends Scenario + with _BasePlatformViewScenarioMixin { + /// Constructs the scenario. + PlatformViewWithNegativeBackDropFilter( + super.view, { + required int id, + }) : _id = id; + + final int _id; + + @override + void onBeginFrame(Duration duration) { + final SceneBuilder builder = SceneBuilder(); + + final PictureRecorder recorder = PictureRecorder(); + final Canvas canvas = Canvas(recorder); + // This is just a background picture to make the result more viewable. + canvas.drawRect( + const Rect.fromLTRB(0, 0, 600, 1000), + Paint()..color = const Color(0xFFFF0000), + ); + canvas.drawRect( + const Rect.fromLTRB(0, 0, 300, 300), + Paint()..color = const Color(0xFF00FF00), + ); + final Picture picture1 = recorder.endRecording(); + builder.addPicture(Offset.zero, picture1); + + builder.pushOffset(0, 200); + + addPlatformView( + _id, + dispatcher: view.platformDispatcher, + sceneBuilder: builder, + width: 100, + height: 100, + text: 'platform view 1' + ); + + final PictureRecorder recorder2 = PictureRecorder(); + final Canvas canvas2 = Canvas(recorder2); + canvas2.drawCircle( + const Offset(200, 100), + 50, + Paint()..color = const Color(0xFF0000EF), + ); + final Picture picture2 = recorder2.endRecording(); + builder.addPicture(const Offset(100, 100), picture2); + + final ImageFilter filter = ImageFilter.blur(sigmaX: -8, sigmaY: 8); + builder.pushBackdropFilter(filter); + + final Scene scene = builder.build(); + view.render(scene); + scene.dispose(); + } +} + /// Builds a scenario where many platform views are scrolling and pass under a picture. class PlatformViewScrollingUnderWidget extends Scenario with _BasePlatformViewScenarioMixin { diff --git a/engine/src/flutter/testing/scenario_app/lib/src/scenarios.dart b/engine/src/flutter/testing/scenario_app/lib/src/scenarios.dart index 9efa352dcc..d9c586023b 100644 --- a/engine/src/flutter/testing/scenario_app/lib/src/scenarios.dart +++ b/engine/src/flutter/testing/scenario_app/lib/src/scenarios.dart @@ -43,6 +43,7 @@ Map _scenarios = { 'platform_view_opacity': (FlutterView view) => PlatformViewOpacityScenario(view, id: _viewId++), 'platform_view_with_other_backdrop_filter': (FlutterView view) => PlatformViewWithOtherBackDropFilter(view, id: _viewId++), 'two_platform_views_with_other_backdrop_filter': (FlutterView view) => TwoPlatformViewsWithOtherBackDropFilter(view, firstId: _viewId++, secondId: _viewId++), + 'platform_view_with_negative_backdrop_filter': (FlutterView view) => PlatformViewWithNegativeBackDropFilter(view, id: _viewId++), 'platform_view_multiple': (FlutterView view) => MultiPlatformViewScenario(view, firstId: _viewId++, secondId: _viewId++), 'platform_view_multiple_background_foreground': (FlutterView view) => MultiPlatformViewBackgroundForegroundScenario(view, firstId: _viewId++, secondId: _viewId++), 'non_full_screen_flutter_view_platform_view': (FlutterView view) => NonFullScreenFlutterViewPlatformViewScenario(view, id: _viewId++),