Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 7ece9bf

Browse files
author
Chris Yang
authored
Revert "Revert "Revert "[ios_platform_view] MaskView pool to reuse maskViews. (#38989)" (#39490)" (#39498)"
This reverts commit 4270d74.
1 parent 99a81a8 commit 7ece9bf

File tree

4 files changed

+16
-241
lines changed

4 files changed

+16
-241
lines changed

shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm

Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h"
1919
#import "flutter/shell/platform/darwin/ios/ios_surface.h"
2020

21-
static const NSUInteger kFlutterClippingMaskViewPoolCapacity = 5;
22-
2321
@implementation UIView (FirstResponder)
2422
- (BOOL)flt_hasFirstResponderInViewHierarchySubtree {
2523
if (self.isFirstResponder) {
@@ -454,17 +452,6 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
454452
return clipCount;
455453
}
456454

457-
void FlutterPlatformViewsController::ClipViewSetMaskView(UIView* clipView) {
458-
if (clipView.maskView) {
459-
return;
460-
}
461-
UIView* flutterView = flutter_view_.get();
462-
CGRect frame =
463-
CGRectMake(-clipView.frame.origin.x, -clipView.frame.origin.y,
464-
CGRectGetWidth(flutterView.bounds), CGRectGetHeight(flutterView.bounds));
465-
clipView.maskView = [mask_view_pool_.get() getMaskViewWithFrame:frame];
466-
}
467-
468455
void FlutterPlatformViewsController::ApplyMutators(const MutatorsStack& mutators_stack,
469456
UIView* embedded_view,
470457
const SkRect& bounding_rect) {
@@ -475,15 +462,18 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
475462
ResetAnchor(embedded_view.layer);
476463
ChildClippingView* clipView = (ChildClippingView*)embedded_view.superview;
477464

465+
CGFloat screenScale = [UIScreen mainScreen].scale;
466+
467+
UIView* flutter_view = flutter_view_.get();
468+
FlutterClippingMaskView* maskView = [[[FlutterClippingMaskView alloc]
469+
initWithFrame:CGRectMake(-clipView.frame.origin.x, -clipView.frame.origin.y,
470+
CGRectGetWidth(flutter_view.bounds),
471+
CGRectGetHeight(flutter_view.bounds))
472+
screenScale:screenScale] autorelease];
473+
478474
SkMatrix transformMatrix;
479475
NSMutableArray* blurFilters = [[[NSMutableArray alloc] init] autorelease];
480-
FML_DCHECK(!clipView.maskView ||
481-
[clipView.maskView isKindOfClass:[FlutterClippingMaskView class]]);
482-
if (mask_view_pool_.get() == nil) {
483-
mask_view_pool_.reset([[FlutterClippingMaskViewPool alloc]
484-
initWithCapacity:kFlutterClippingMaskViewPoolCapacity]);
485-
}
486-
[mask_view_pool_.get() recycleMaskViews];
476+
487477
clipView.maskView = nil;
488478
CGFloat screenScale = [UIScreen mainScreen].scale;
489479
auto iter = mutators_stack.Begin();
@@ -498,28 +488,25 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
498488
transformMatrix)) {
499489
break;
500490
}
501-
ClipViewSetMaskView(clipView);
502-
[(FlutterClippingMaskView*)clipView.maskView clipRect:(*iter)->GetRect()
503-
matrix:transformMatrix];
491+
[maskView clipRect:(*iter)->GetRect() matrix:transformMatrix];
492+
clipView.maskView = maskView;
504493
break;
505494
}
506495
case kClipRRect: {
507496
if (ClipRRectContainsPlatformViewBoundingRect((*iter)->GetRRect(), bounding_rect,
508497
transformMatrix)) {
509498
break;
510499
}
511-
ClipViewSetMaskView(clipView);
512-
[(FlutterClippingMaskView*)clipView.maskView clipRRect:(*iter)->GetRRect()
513-
matrix:transformMatrix];
500+
[maskView clipRRect:(*iter)->GetRRect() matrix:transformMatrix];
501+
clipView.maskView = maskView;
514502
break;
515503
}
516504
case kClipPath: {
517505
// TODO(cyanglaz): Find a way to pre-determine if path contains the PlatformView boudning
518506
// rect. See `ClipRRectContainsPlatformViewBoundingRect`.
519507
// https://github.com/flutter/flutter/issues/118650
520-
ClipViewSetMaskView(clipView);
521-
[(FlutterClippingMaskView*)clipView.maskView clipPath:(*iter)->GetPath()
522-
matrix:transformMatrix];
508+
[maskView clipPath:(*iter)->GetPath() matrix:transformMatrix];
509+
clipView.maskView = maskView;
523510
break;
524511
}
525512
case kOpacity:

shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm

Lines changed: 0 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -2455,125 +2455,6 @@ - (void)testHasFirstResponderInViewHierarchySubtree_descendantViewBecomesFirstRe
24552455
XCTAssertFalse(view.flt_hasFirstResponderInViewHierarchySubtree);
24562456
}
24572457

2458-
- (void)testFlutterClippingMaskViewPoolReuseViewsAfterRecycle {
2459-
FlutterClippingMaskViewPool* pool =
2460-
[[[FlutterClippingMaskViewPool alloc] initWithCapacity:2] autorelease];
2461-
FlutterClippingMaskView* view1 = [pool getMaskViewWithFrame:CGRectZero];
2462-
FlutterClippingMaskView* view2 = [pool getMaskViewWithFrame:CGRectZero];
2463-
[pool recycleMaskViews];
2464-
CGRect newRect = CGRectMake(0, 0, 10, 10);
2465-
FlutterClippingMaskView* view3 = [pool getMaskViewWithFrame:newRect];
2466-
FlutterClippingMaskView* view4 = [pool getMaskViewWithFrame:newRect];
2467-
XCTAssertEqual(view1, view3);
2468-
XCTAssertEqual(view2, view4);
2469-
XCTAssertTrue(CGRectEqualToRect(view3.frame, newRect));
2470-
XCTAssertTrue(CGRectEqualToRect(view4.frame, newRect));
2471-
}
2472-
2473-
- (void)testFlutterClippingMaskViewPoolAllocsNewMaskViewsAfterReachingCapacity {
2474-
FlutterClippingMaskViewPool* pool =
2475-
[[[FlutterClippingMaskViewPool alloc] initWithCapacity:2] autorelease];
2476-
FlutterClippingMaskView* view1 = [pool getMaskViewWithFrame:CGRectZero];
2477-
FlutterClippingMaskView* view2 = [pool getMaskViewWithFrame:CGRectZero];
2478-
FlutterClippingMaskView* view3 = [pool getMaskViewWithFrame:CGRectZero];
2479-
XCTAssertNotEqual(view1, view3);
2480-
XCTAssertNotEqual(view2, view3);
2481-
}
2482-
2483-
- (void)testMaskViewsReleasedWhenPoolIsReleased {
2484-
UIView* retainedView;
2485-
@autoreleasepool {
2486-
FlutterClippingMaskViewPool* pool =
2487-
[[[FlutterClippingMaskViewPool alloc] initWithCapacity:2] autorelease];
2488-
FlutterClippingMaskView* view = [pool getMaskViewWithFrame:CGRectZero];
2489-
retainedView = [view retain];
2490-
XCTAssertGreaterThan(retainedView.retainCount, 1u);
2491-
}
2492-
// The only retain left is our manual retain called inside the autorelease pool, meaning the
2493-
// maskViews are dealloc'd.
2494-
XCTAssertEqual(retainedView.retainCount, 1u);
2495-
}
2496-
2497-
- (void)testClipMaskViewIsReused {
2498-
flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
2499-
auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
2500-
flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
2501-
/*platform=*/thread_task_runner,
2502-
/*raster=*/thread_task_runner,
2503-
/*ui=*/thread_task_runner,
2504-
/*io=*/thread_task_runner);
2505-
auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
2506-
auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2507-
/*delegate=*/mock_delegate,
2508-
/*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
2509-
/*platform_views_controller=*/flutterPlatformViewsController,
2510-
/*task_runners=*/runners);
2511-
2512-
FlutterPlatformViewsTestMockFlutterPlatformFactory* factory =
2513-
[[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease];
2514-
flutterPlatformViewsController->RegisterViewFactory(
2515-
factory, @"MockFlutterPlatformView",
2516-
FlutterPlatformViewGestureRecognizersBlockingPolicyEager);
2517-
FlutterResult result = ^(id result) {
2518-
};
2519-
flutterPlatformViewsController->OnMethodCall(
2520-
[FlutterMethodCall
2521-
methodCallWithMethodName:@"create"
2522-
arguments:@{@"id" : @1, @"viewType" : @"MockFlutterPlatformView"}],
2523-
result);
2524-
2525-
XCTAssertNotNil(gMockPlatformView);
2526-
UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)] autorelease];
2527-
flutterPlatformViewsController->SetFlutterView(mockFlutterView);
2528-
// Create embedded view params
2529-
flutter::MutatorsStack stack1;
2530-
// Layer tree always pushes a screen scale factor to the stack
2531-
SkMatrix screenScaleMatrix =
2532-
SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale);
2533-
stack1.PushTransform(screenScaleMatrix);
2534-
// Push a clip rect
2535-
SkRect rect = SkRect::MakeXYWH(2, 2, 3, 3);
2536-
stack1.PushClipRect(rect);
2537-
2538-
auto embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>(
2539-
screenScaleMatrix, SkSize::Make(10, 10), stack1);
2540-
2541-
flutter::MutatorsStack stack2;
2542-
auto embeddedViewParams2 = std::make_unique<flutter::EmbeddedViewParams>(
2543-
screenScaleMatrix, SkSize::Make(10, 10), stack2);
2544-
2545-
flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams1));
2546-
flutterPlatformViewsController->CompositeEmbeddedView(1);
2547-
UIView* childClippingView1 = gMockPlatformView.superview.superview;
2548-
UIView* maskView1 = childClippingView1.maskView;
2549-
XCTAssertNotNil(maskView1);
2550-
2551-
// Composite a new frame.
2552-
auto embeddedViewParams3 = std::make_unique<flutter::EmbeddedViewParams>(
2553-
screenScaleMatrix, SkSize::Make(10, 10), stack2);
2554-
flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams3));
2555-
flutterPlatformViewsController->CompositeEmbeddedView(1);
2556-
childClippingView1 = gMockPlatformView.superview.superview;
2557-
2558-
// This overrides gMockPlatformView to point to the newly created platform view.
2559-
flutterPlatformViewsController->OnMethodCall(
2560-
[FlutterMethodCall
2561-
methodCallWithMethodName:@"create"
2562-
arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
2563-
result);
2564-
2565-
auto embeddedViewParams4 = std::make_unique<flutter::EmbeddedViewParams>(
2566-
screenScaleMatrix, SkSize::Make(10, 10), stack1);
2567-
flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams4));
2568-
flutterPlatformViewsController->CompositeEmbeddedView(2);
2569-
UIView* childClippingView2 = gMockPlatformView.superview.superview;
2570-
2571-
UIView* maskView2 = childClippingView2.maskView;
2572-
XCTAssertEqual(maskView1, maskView2);
2573-
XCTAssertNotNil(childClippingView2.maskView);
2574-
XCTAssertNil(childClippingView1.maskView);
2575-
}
2576-
25772458
// Return true if a correct visual effect view is found. It also implies all the validation in this
25782459
// method passes.
25792460
//

shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@
3030

3131
- (instancetype)initWithFrame:(CGRect)frame screenScale:(CGFloat)screenScale;
3232

33-
- (void)reset;
34-
3533
// Adds a clip rect operation to the queue.
3634
//
3735
// The `clipSkRect` is transformed with the `matrix` before adding to the queue.
@@ -49,28 +47,6 @@
4947

5048
@end
5149

52-
// A pool that provides |FlutterClippingMaskView|s.
53-
//
54-
// The pool has a capacity that can be set in the initializer.
55-
// When requesting a FlutterClippingMaskView, the pool will first try to reuse an available maskView
56-
// in the pool. If there are none available, a new FlutterClippingMaskView is constructed. If the
57-
// capacity is reached, the newly constructed FlutterClippingMaskView is not added to the pool.
58-
//
59-
// Call |recycleMaskViews| to mark all the FlutterClippingMaskViews in the pool available.
60-
@interface FlutterClippingMaskViewPool : NSObject
61-
62-
// Initialize the pool with `capacity`. When the `capacity` is reached, a FlutterClippingMaskView is
63-
// constructed when requested, and it is not added to the pool.
64-
- (instancetype)initWithCapacity:(NSInteger)capacity;
65-
66-
// Reuse a maskView from the pool, or allocate a new one.
67-
- (FlutterClippingMaskView*)getMaskViewWithFrame:(CGRect)frame;
68-
69-
// Mark all the maskViews available.
70-
- (void)recycleMaskViews;
71-
72-
@end
73-
7450
// An object represents a blur filter.
7551
//
7652
// This object produces a `backdropFilterView`.
@@ -292,7 +268,6 @@ class FlutterPlatformViewsController {
292268
// Traverse the `mutators_stack` and return the number of clip operations.
293269
int CountClips(const MutatorsStack& mutators_stack);
294270

295-
void ClipViewSetMaskView(UIView* clipView);
296271
// Applies the mutators in the mutators_stack to the UIView chain that was constructed by
297272
// `ReconstructClipViewsChain`
298273
//
@@ -353,7 +328,6 @@ class FlutterPlatformViewsController {
353328
fml::scoped_nsobject<FlutterMethodChannel> channel_;
354329
fml::scoped_nsobject<UIView> flutter_view_;
355330
fml::scoped_nsobject<UIViewController> flutter_view_controller_;
356-
fml::scoped_nsobject<FlutterClippingMaskViewPool> mask_view_pool_;
357331
std::map<std::string, fml::scoped_nsobject<NSObject<FlutterPlatformViewFactory>>> factories_;
358332
std::map<int64_t, fml::scoped_nsobject<NSObject<FlutterPlatformView>>> views_;
359333
std::map<int64_t, fml::scoped_nsobject<FlutterTouchInterceptingView>> touch_interceptors_;

shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm

Lines changed: 0 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -271,10 +271,6 @@ - (instancetype)initWithFrame:(CGRect)frame screenScale:(CGFloat)screenScale {
271271
return self;
272272
}
273273

274-
- (void)reset {
275-
paths_.clear();
276-
}
277-
278274
// In some scenarios, when we add this view as a maskView of the ChildClippingView, iOS added
279275
// this view as a subview of the ChildClippingView.
280276
// This results this view blocking touch events on the ChildClippingView.
@@ -451,66 +447,3 @@ - (void)clipPath:(const SkPath&)path matrix:(const SkMatrix&)matrix {
451447
}
452448

453449
@end
454-
455-
@interface FlutterClippingMaskViewPool ()
456-
457-
// The maximum number of `FlutterClippingMaskView` the pool can contain.
458-
// This prevents the pool to grow infinately and limits the maximum memory a pool can use.
459-
@property(assign, nonatomic) NSUInteger capacity;
460-
@property(retain, nonatomic) NSMutableArray<FlutterClippingMaskView*>* pool;
461-
// The index points to the first available FlutterClippingMaskView in the `pool`.
462-
@property(assign, nonatomic) NSUInteger availableIndex;
463-
464-
@end
465-
466-
@implementation FlutterClippingMaskViewPool : NSObject
467-
468-
- (instancetype)initWithCapacity:(NSInteger)capacity {
469-
if (self = [super init]) {
470-
_pool = [[NSMutableArray alloc] initWithCapacity:capacity];
471-
_capacity = capacity;
472-
_availableIndex = 0;
473-
}
474-
return self;
475-
}
476-
477-
- (FlutterClippingMaskView*)getMaskViewWithFrame:(CGRect)frame {
478-
FML_DCHECK(self.availableIndex <= self.capacity);
479-
FlutterClippingMaskView* maskView;
480-
if (self.availableIndex == self.capacity) {
481-
// The pool is full, alloc a new one.
482-
maskView =
483-
[[[FlutterClippingMaskView alloc] initWithFrame:frame
484-
screenScale:[UIScreen mainScreen].scale] autorelease];
485-
return maskView;
486-
}
487-
488-
if (self.availableIndex >= self.pool.count) {
489-
// The pool doesn't have enough maskViews, alloc a new one and add to the pool.
490-
maskView =
491-
[[[FlutterClippingMaskView alloc] initWithFrame:frame
492-
screenScale:[UIScreen mainScreen].scale] autorelease];
493-
[self.pool addObject:maskView];
494-
FML_DCHECK(self.pool.count <= self.capacity);
495-
} else {
496-
// Reuse a maskView from the pool.
497-
maskView = [self.pool objectAtIndex:self.availableIndex];
498-
maskView.frame = frame;
499-
[maskView reset];
500-
}
501-
self.availableIndex++;
502-
return maskView;
503-
}
504-
505-
- (void)recycleMaskViews {
506-
self.availableIndex = 0;
507-
}
508-
509-
- (void)dealloc {
510-
[_pool release];
511-
_pool = nil;
512-
513-
[super dealloc];
514-
}
515-
516-
@end

0 commit comments

Comments
 (0)