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

Commit 6a2de77

Browse files
author
Chris Yang
authored
Revert "[ios_platform_view] MaskView pool to reuse maskViews. (#38989)" (#39490)
This reverts commit 2ee8257.
1 parent ef9d3e9 commit 6a2de77

File tree

4 files changed

+16
-242
lines changed

4 files changed

+16
-242
lines changed

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

Lines changed: 16 additions & 30 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) {
@@ -453,17 +451,6 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
453451
return clipCount;
454452
}
455453

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

464+
CGFloat screenScale = [UIScreen mainScreen].scale;
465+
466+
UIView* flutter_view = flutter_view_.get();
467+
FlutterClippingMaskView* maskView = [[[FlutterClippingMaskView alloc]
468+
initWithFrame:CGRectMake(-clipView.frame.origin.x, -clipView.frame.origin.y,
469+
CGRectGetWidth(flutter_view.bounds),
470+
CGRectGetHeight(flutter_view.bounds))
471+
screenScale:screenScale] autorelease];
472+
477473
SkMatrix transformMatrix;
478474
NSMutableArray* blurFilters = [[[NSMutableArray alloc] init] autorelease];
479-
FML_DCHECK(!clipView.maskView ||
480-
[clipView.maskView isKindOfClass:[FlutterClippingMaskView class]]);
481-
if (mask_view_pool_.get() == nil) {
482-
mask_view_pool_.reset([[FlutterClippingMaskViewPool alloc]
483-
initWithCapacity:kFlutterClippingMaskViewPoolCapacity]);
484-
}
485-
[mask_view_pool_.get() recycleMaskViews];
475+
486476
clipView.maskView = nil;
487477
auto iter = mutators_stack.Begin();
488478
while (iter != mutators_stack.End()) {
@@ -496,28 +486,25 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
496486
transformMatrix)) {
497487
break;
498488
}
499-
ClipViewSetMaskView(clipView);
500-
[(FlutterClippingMaskView*)clipView.maskView clipRect:(*iter)->GetRect()
501-
matrix:transformMatrix];
489+
[maskView clipRect:(*iter)->GetRect() matrix:transformMatrix];
490+
clipView.maskView = maskView;
502491
break;
503492
}
504493
case kClipRRect: {
505494
if (ClipRRectContainsPlatformViewBoundingRect((*iter)->GetRRect(), bounding_rect,
506495
transformMatrix)) {
507496
break;
508497
}
509-
ClipViewSetMaskView(clipView);
510-
[(FlutterClippingMaskView*)clipView.maskView clipRRect:(*iter)->GetRRect()
511-
matrix:transformMatrix];
498+
[maskView clipRRect:(*iter)->GetRRect() matrix:transformMatrix];
499+
clipView.maskView = maskView;
512500
break;
513501
}
514502
case kClipPath: {
515503
// TODO(cyanglaz): Find a way to pre-determine if path contains the PlatformView boudning
516504
// rect. See `ClipRRectContainsPlatformViewBoundingRect`.
517505
// https://github.com/flutter/flutter/issues/118650
518-
ClipViewSetMaskView(clipView);
519-
[(FlutterClippingMaskView*)clipView.maskView clipPath:(*iter)->GetPath()
520-
matrix:transformMatrix];
506+
[maskView clipPath:(*iter)->GetPath() matrix:transformMatrix];
507+
clipView.maskView = maskView;
521508
break;
522509
}
523510
case kOpacity:
@@ -564,7 +551,6 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
564551
[clipView applyBlurBackdropFilters:blurFilters];
565552
}
566553

567-
CGFloat screenScale = [UIScreen mainScreen].scale;
568554
// The UIKit frame is set based on the logical resolution (points) instead of physical.
569555
// (https://developer.apple.com/library/archive/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Displays/Displays.html).
570556
// However, flow is based on the physical resolution. For example, 1000 pixels in flow equals

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

Lines changed: 0 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -2445,125 +2445,6 @@ - (void)testHasFirstResponderInViewHierarchySubtree_descendantViewBecomesFirstRe
24452445
XCTAssertFalse(view.flt_hasFirstResponderInViewHierarchySubtree);
24462446
}
24472447

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

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)