-
Notifications
You must be signed in to change notification settings - Fork 6k
[ios_platform_view] only recycle maskView when the view is applying mutators #41573
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -56,7 +56,7 @@ | |
| // in the pool. If there are none available, a new FlutterClippingMaskView is constructed. If the | ||
| // capacity is reached, the newly constructed FlutterClippingMaskView is not added to the pool. | ||
| // | ||
| // Call |recycleMaskViews| to mark all the FlutterClippingMaskViews in the pool available. | ||
| // Call |insertViewToPool:| to return a maskView to the pool. | ||
| @interface FlutterClippingMaskViewPool : NSObject | ||
|
|
||
| // Initialize the pool with `capacity`. When the `capacity` is reached, a FlutterClippingMaskView is | ||
|
|
@@ -66,8 +66,8 @@ | |
| // Reuse a maskView from the pool, or allocate a new one. | ||
| - (FlutterClippingMaskView*)getMaskViewWithFrame:(CGRect)frame; | ||
|
|
||
| // Mark all the maskViews available. | ||
| - (void)recycleMaskViews; | ||
| // Insert the `maskView` into the pool. | ||
| - (void)insertViewToPool:(FlutterClippingMaskView*)maskView; | ||
|
|
||
| @end | ||
|
|
||
|
|
@@ -291,27 +291,30 @@ class FlutterPlatformViewsController { | |
| int CountClips(const MutatorsStack& mutators_stack); | ||
|
|
||
| void ClipViewSetMaskView(UIView* clipView); | ||
|
|
||
| // Applies the mutators in the mutators_stack to the UIView chain that was constructed by | ||
| // `ReconstructClipViewsChain` | ||
| // | ||
| // Clips are applied to the super view with a CALayer mask. Transforms are applied to the | ||
| // current view that's at the head of the chain. For example the following mutators stack [T_1, | ||
| // C_2, T_3, T_4, C_5, T_6] where T denotes a transform and C denotes a clip, will result in the | ||
| // following UIView tree: | ||
| // | ||
| // C_2 -> C_5 -> PLATFORM_VIEW | ||
| // (PLATFORM_VIEW is a subview of C_5 which is a subview of C_2) | ||
| // | ||
| // T_1 is applied to C_2, T_3 and T_4 are applied to C_5, and T_6 is applied to PLATFORM_VIEW. | ||
| // | ||
| // After each clip operation, we update the head to the super view of the current head. | ||
| // Clips are applied to the `embedded_view`'s super view(|ChildClippingView|) using a | ||
| // |FlutterClippingMaskView|. Transforms are applied to `embedded_view` | ||
| // | ||
| // The `bounding_rect` is the final bounding rect of the PlatformView | ||
| // (EmbeddedViewParams::finalBoundingRect). If a clip mutator's rect contains the final bounding | ||
| // rect of the PlatformView, the clip mutator is not applied for performance optimization. | ||
| // | ||
| // This method is only called when thew `embedded_view` needs to be re-composited at the current | ||
| // frame. See: `CompositeWithParams` for details. | ||
| void ApplyMutators(const MutatorsStack& mutators_stack, | ||
| UIView* embedded_view, | ||
| const SkRect& bounding_rect); | ||
|
|
||
| // Composite the PlatformView with `view_id`. | ||
| // Every frame, during the paint traversal of the layer tree, this method is called for all | ||
| // the PlatformViews in `views_to_recomposite_`. | ||
| // | ||
| // Note that `views_to_recomposite_` does not represent all the views in the view hierarchy, | ||
| // if a PlatformView does not change its composition parameter from last frame, it is not | ||
| // included in the `views_to_recomposite_`. | ||
|
||
| void CompositeWithParams(int64_t view_id, const EmbeddedViewParams& params); | ||
|
|
||
| // Allocates a new FlutterPlatformViewLayer if needed, draws the pixels within the rect from | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,7 @@ | |
| #import "flutter/shell/platform/darwin/ios/ios_surface.h" | ||
|
|
||
| static int kMaxPointsInVerb = 4; | ||
| static const NSUInteger kFlutterClippingMaskViewPoolCapacity = 5; | ||
|
|
||
| namespace flutter { | ||
|
|
||
|
|
@@ -26,7 +27,10 @@ | |
|
|
||
| FlutterPlatformViewsController::FlutterPlatformViewsController() | ||
| : layer_pool_(std::make_unique<FlutterPlatformViewLayerPool>()), | ||
| weak_factory_(std::make_unique<fml::WeakPtrFactory<FlutterPlatformViewsController>>(this)){}; | ||
| weak_factory_(std::make_unique<fml::WeakPtrFactory<FlutterPlatformViewsController>>(this)) { | ||
| mask_view_pool_.reset( | ||
| [[FlutterClippingMaskViewPool alloc] initWithCapacity:kFlutterClippingMaskViewPoolCapacity]); | ||
| }; | ||
|
|
||
| FlutterPlatformViewsController::~FlutterPlatformViewsController() = default; | ||
|
|
||
|
|
@@ -458,58 +462,51 @@ @interface FlutterClippingMaskViewPool () | |
| // The maximum number of `FlutterClippingMaskView` the pool can contain. | ||
| // This prevents the pool to grow infinately and limits the maximum memory a pool can use. | ||
| @property(assign, nonatomic) NSUInteger capacity; | ||
| @property(retain, nonatomic) NSMutableArray<FlutterClippingMaskView*>* pool; | ||
| // The index points to the first available FlutterClippingMaskView in the `pool`. | ||
| @property(assign, nonatomic) NSUInteger availableIndex; | ||
|
|
||
| // The pool contains the views that are available to use. | ||
| // The number of items in the pool must not excceds `capacity`. | ||
| @property(retain, nonatomic) NSMutableSet<FlutterClippingMaskView*>* pool; | ||
|
|
||
| @end | ||
|
|
||
| @implementation FlutterClippingMaskViewPool : NSObject | ||
|
|
||
| - (instancetype)initWithCapacity:(NSInteger)capacity { | ||
| if (self = [super init]) { | ||
| _pool = [[NSMutableArray alloc] initWithCapacity:capacity]; | ||
| _pool = [[NSMutableSet alloc] init]; | ||
|
||
| _capacity = capacity; | ||
| _availableIndex = 0; | ||
| } | ||
| return self; | ||
| } | ||
|
|
||
| - (FlutterClippingMaskView*)getMaskViewWithFrame:(CGRect)frame { | ||
| FML_DCHECK(self.availableIndex <= self.capacity); | ||
| FML_DCHECK(self.pool.count <= self.capacity); | ||
| FlutterClippingMaskView* maskView; | ||
| if (self.availableIndex == self.capacity) { | ||
| // The pool is full, alloc a new one. | ||
| if (self.pool.count == 0) { | ||
| // The pool is empty, alloc a new one. | ||
| maskView = | ||
| [[[FlutterClippingMaskView alloc] initWithFrame:frame | ||
| screenScale:[UIScreen mainScreen].scale] autorelease]; | ||
| return maskView; | ||
| } | ||
|
|
||
| if (self.availableIndex >= self.pool.count) { | ||
| // The pool doesn't have enough maskViews, alloc a new one and add to the pool. | ||
| maskView = | ||
| [[[FlutterClippingMaskView alloc] initWithFrame:frame | ||
| screenScale:[UIScreen mainScreen].scale] autorelease]; | ||
| [self.pool addObject:maskView]; | ||
| FML_DCHECK(self.pool.count <= self.capacity); | ||
| } else { | ||
| // Reuse a maskView from the pool. | ||
| maskView = [self.pool objectAtIndex:self.availableIndex]; | ||
| maskView.frame = frame; | ||
| [maskView reset]; | ||
| } | ||
| self.availableIndex++; | ||
| maskView = [self.pool anyObject]; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How do you know if this view is available for reuse?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When the view is in use, it is removed from the pool: |
||
| maskView.frame = frame; | ||
| [maskView reset]; | ||
| [self.pool removeObject:maskView]; | ||
| return maskView; | ||
| } | ||
|
|
||
| - (void)recycleMaskViews { | ||
| self.availableIndex = 0; | ||
| - (void)insertViewToPool:(FlutterClippingMaskView*)maskView { | ||
|
||
| FML_DCHECK(![self.pool containsObject:maskView]); | ||
| FML_DCHECK(self.pool.count <= self.capacity); | ||
| if (self.pool.count == self.capacity) { | ||
| return; | ||
| } | ||
| [self.pool addObject:maskView]; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The user of the maskView decides to insert the view back to the pool when they are done with the maskView
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: need to add capacity check here. |
||
| } | ||
|
|
||
| - (void)dealloc { | ||
| [_pool release]; | ||
| _pool = nil; | ||
|
|
||
| [super dealloc]; | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo