7 #include "flutter/display_list/effects/image_filters/dl_blur_image_filter.h"
8 #include "flutter/flow/surface_frame.h"
9 #include "flutter/flow/view_slicer.h"
10 #include "flutter/fml/make_copyable.h"
11 #include "flutter/fml/synchronization/count_down_latch.h"
29 std::shared_ptr<flutter::OverlayLayer>
layer;
31 using LayersMap = std::unordered_map<int64_t, LayerData>;
38 NSObject<FlutterPlatformView>*
view;
48 CATransform3D transform = CATransform3DIdentity;
49 transform.m11 = matrix.getScaleX();
50 transform.m21 = matrix.getSkewX();
51 transform.m41 = matrix.getTranslateX();
52 transform.m14 = matrix.getPerspX();
54 transform.m12 = matrix.getSkewY();
55 transform.m22 = matrix.getScaleY();
56 transform.m42 = matrix.getTranslateY();
57 transform.m24 = matrix.getPerspY();
66 layer.anchorPoint = CGPointZero;
67 layer.position = CGPointZero;
71 return CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight - clipSkRect.fLeft,
72 clipSkRect.fBottom - clipSkRect.fTop);
84 const SkRect& platformview_boundingrect,
85 const SkMatrix& transform_matrix) {
86 SkRect transformed_rect = transform_matrix.mapRect(clip_rect);
87 return transformed_rect.contains(platformview_boundingrect);
99 const SkRect& platformview_boundingrect,
100 const SkMatrix& transform_matrix) {
101 SkVector upper_left = clip_rrect.radii(SkRRect::Corner::kUpperLeft_Corner);
102 SkVector upper_right = clip_rrect.radii(SkRRect::Corner::kUpperRight_Corner);
103 SkVector lower_right = clip_rrect.radii(SkRRect::Corner::kLowerRight_Corner);
104 SkVector lower_left = clip_rrect.radii(SkRRect::Corner::kLowerLeft_Corner);
105 SkScalar transformed_upper_left_x = transform_matrix.mapRadius(upper_left.x());
106 SkScalar transformed_upper_left_y = transform_matrix.mapRadius(upper_left.y());
107 SkScalar transformed_upper_right_x = transform_matrix.mapRadius(upper_right.x());
108 SkScalar transformed_upper_right_y = transform_matrix.mapRadius(upper_right.y());
109 SkScalar transformed_lower_right_x = transform_matrix.mapRadius(lower_right.x());
110 SkScalar transformed_lower_right_y = transform_matrix.mapRadius(lower_right.y());
111 SkScalar transformed_lower_left_x = transform_matrix.mapRadius(lower_left.x());
112 SkScalar transformed_lower_left_y = transform_matrix.mapRadius(lower_left.y());
113 SkRect transformed_clip_rect = transform_matrix.mapRect(clip_rrect.rect());
114 SkRRect transformed_rrect;
115 SkVector corners[] = {{transformed_upper_left_x, transformed_upper_left_y},
116 {transformed_upper_right_x, transformed_upper_right_y},
117 {transformed_lower_right_x, transformed_lower_right_y},
118 {transformed_lower_left_x, transformed_lower_left_y}};
119 transformed_rrect.setRectRadii(transformed_clip_rect, corners);
120 return transformed_rrect.contains(platformview_boundingrect);
132 @property(nonatomic, readonly)
133 std::unordered_map<int64_t, std::unique_ptr<flutter::EmbedderViewSlice>>& slices;
137 @property(nonatomic, readonly)
138 std::unordered_map<std::string, NSObject<FlutterPlatformViewFactory>*>& factories;
141 @property(nonatomic, readonly)
142 std::unordered_map<std::string, FlutterPlatformViewGestureRecognizersBlockingPolicy>&
143 gestureRecognizersBlockingPolicies;
146 @property(nonatomic, assign) SkISize frameSize;
149 @property(nonatomic, readonly)
const fml::RefPtr<fml::TaskRunner>& platformTaskRunner;
152 @property(nonatomic, readonly) std::unordered_map<int64_t, PlatformViewData>& platformViews;
157 @property(nonatomic, readonly)
158 std::unordered_map<int64_t, flutter::EmbeddedViewParams>& currentCompositionParams;
164 @property(nonatomic, readonly) std::unordered_set<int64_t>& viewsToDispose;
169 @property(nonatomic, readonly) std::vector<int64_t>& compositionOrder;
174 @property(nonatomic, readonly) std::vector<int64_t>& visitedPlatformViews;
179 @property(nonatomic, readonly) std::unordered_set<int64_t>& viewsToRecomposite;
184 @property(nonatomic, readonly) std::vector<int64_t>& previousCompositionOrder;
193 @property(nonatomic, assign) BOOL hadPlatformViews;
198 @property(nonatomic, assign) BOOL canApplyBlurBackdrop;
203 - (void)createMissingOverlays:(
size_t)requiredOverlayLayers
204 withIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext
205 grContext:(GrDirectContext*)grContext;
208 - (void)performSubmit:(const
LayersMap&)platformViewLayers
209 currentCompositionParams:
210 (std::unordered_map<int64_t,
flutter::EmbeddedViewParams>&)currentCompositionParams
211 viewsToRecomposite:(const std::unordered_set<int64_t>&)viewsToRecomposite
212 compositionOrder:(const std::vector<int64_t>&)compositionOrder
214 (const std::vector<std::shared_ptr<
flutter::OverlayLayer>>&)unusedLayers
216 (const std::vector<std::unique_ptr<
flutter::SurfaceFrame>>&)surfaceFrames;
223 - (void)clipViewSetMaskView:(UIView*)clipView;
237 - (void)applyMutators:(const
flutter::MutatorsStack&)mutatorsStack
238 embeddedView:(UIView*)embeddedView
239 boundingRect:(const SkRect&)boundingRect;
243 - (void)bringLayersIntoView:(const
LayersMap&)layerMap
244 withCompositionOrder:(const std::vector<int64_t>&)compositionOrder;
246 - (std::shared_ptr<flutter::OverlayLayer>)nextLayerInPool;
249 - (void)createLayerWithIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext
250 grContext:(GrDirectContext*)grContext
251 pixelFormat:(MTLPixelFormat)pixelFormat;
255 - (void)removeUnusedLayers:(const std::vector<std::shared_ptr<
flutter::OverlayLayer>>&)unusedLayers
256 withCompositionOrder:(const std::vector<int64_t>&)compositionOrder;
262 - (std::vector<UIView*>)computeViewsToDispose;
265 - (void)resetFrameState;
276 std::unique_ptr<flutter::OverlayLayerPool> _layerPool;
277 std::unordered_map<int64_t, std::unique_ptr<flutter::EmbedderViewSlice>>
_slices;
278 std::unordered_map<std::string, NSObject<FlutterPlatformViewFactory>*>
_factories;
279 std::unordered_map<std::string, FlutterPlatformViewGestureRecognizersBlockingPolicy>
292 if (
self = [super init]) {
293 _layerPool = std::make_unique<flutter::OverlayLayerPool>();
296 _hadPlatformViews = NO;
297 _canApplyBlurBackdrop = YES;
302 - (const
fml::RefPtr<fml::TaskRunner>&)taskRunner {
306 - (void)setTaskRunner:(const
fml::RefPtr<
fml::TaskRunner>&)platformTaskRunner {
311 if ([[call method] isEqualToString:
@"create"]) {
312 [
self onCreate:call result:result];
313 }
else if ([[call method] isEqualToString:
@"dispose"]) {
314 [
self onDispose:call result:result];
315 }
else if ([[call method] isEqualToString:
@"acceptGesture"]) {
316 [
self onAcceptGesture:call result:result];
317 }
else if ([[call method] isEqualToString:
@"rejectGesture"]) {
318 [
self onRejectGesture:call result:result];
325 NSDictionary<NSString*, id>* args = [call
arguments];
327 int64_t viewId = [args[@"id"] longLongValue];
328 NSString* viewTypeString = args[@"viewType"];
329 std::string viewType(viewTypeString.UTF8String);
331 if (
self.platformViews.count(viewId) != 0) {
333 message:
@"trying to create an already created view"
334 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
338 NSObject<FlutterPlatformViewFactory>* factory =
self.factories[viewType];
339 if (factory == nil) {
341 errorWithCode:
@"unregistered_view_type"
342 message:[NSString stringWithFormat:
@"A UIKitView widget is trying to create a "
343 @"PlatformView with an unregistered type: < %@ >",
345 details:
@"If you are the author of the PlatformView, make sure `registerViewFactory` "
348 @"https://docs.flutter.cn/development/platform-integration/"
349 @"platform-views#on-the-platform-side-1 for more details.\n"
350 @"If you are not the author of the PlatformView, make sure to call "
351 @"`GeneratedPluginRegistrant.register`."]);
356 if ([factory respondsToSelector:
@selector(createArgsCodec)]) {
357 NSObject<FlutterMessageCodec>* codec = [factory createArgsCodec];
358 if (codec != nil && args[
@"params"] != nil) {
360 params = [codec decode:paramsData.data];
364 NSObject<FlutterPlatformView>* embeddedView = [factory createWithFrame:CGRectZero
365 viewIdentifier:viewId
367 UIView* platformView = [embeddedView view];
369 platformView.accessibilityIdentifier = [NSString stringWithFormat:@"platform_view[%lld]", viewId];
372 initWithEmbeddedView:platformView
373 platformViewsController:self
374 gestureRecognizersBlockingPolicy:self.gestureRecognizersBlockingPolicies[viewType]];
377 [clippingView addSubview:touchInterceptor];
380 .
view = embeddedView,
381 .touch_interceptor = touchInterceptor,
382 .root_view = clippingView
390 int64_t viewId = [arg longLongValue];
392 if (
self.platformViews.count(viewId) == 0) {
394 message:
@"trying to dispose an unknown"
395 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
399 self.viewsToDispose.insert(viewId);
404 NSDictionary<NSString*, id>* args = [call
arguments];
405 int64_t viewId = [args[@"id"] longLongValue];
407 if (
self.platformViews.count(viewId) == 0) {
409 message:
@"trying to set gesture state for an unknown view"
410 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
421 NSDictionary<NSString*, id>* args = [call
arguments];
422 int64_t viewId = [args[@"id"] longLongValue];
424 if (
self.platformViews.count(viewId) == 0) {
426 message:
@"trying to set gesture state for an unknown view"
427 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
438 withId:(NSString*)factoryId
439 gestureRecognizersBlockingPolicy:
441 std::string idString([factoryId UTF8String]);
442 FML_CHECK(
self.factories.count(idString) == 0);
443 self.factories[idString] = factory;
444 self.gestureRecognizersBlockingPolicies[idString] = gestureRecognizerBlockingPolicy;
447 - (void)beginFrameWithSize:(SkISize)frameSize {
448 [
self resetFrameState];
449 self.frameSize = frameSize;
452 - (void)cancelFrame {
453 [
self resetFrameState];
456 - (
flutter::PostPrerollResult)postPrerollActionWithThreadMerger:
457 (const
fml::RefPtr<
fml::RasterThreadMerger>&)rasterThreadMerger
458 impellerEnabled:(BOOL)impellerEnabled {
460 #ifdef FML_OS_IOS_SIMULATOR
461 const bool mergeThreads =
true;
463 const bool mergeThreads = !impellerEnabled;
464 #endif // FML_OS_IOS_SIMULATOR
467 if (
self.compositionOrder.empty()) {
468 return flutter::PostPrerollResult::kSuccess;
470 if (!rasterThreadMerger->IsMerged()) {
480 return flutter::PostPrerollResult::kSkipAndRetryFrame;
488 return flutter::PostPrerollResult::kSuccess;
491 - (void)endFrameWithResubmit:(BOOL)shouldResubmitFrame
492 threadMerger:(const
fml::RefPtr<
fml::RasterThreadMerger>&)rasterThreadMerger
493 impellerEnabled:(BOOL)impellerEnabled {
494 #if FML_OS_IOS_SIMULATOR
497 BOOL runCheck = !impellerEnabled;
498 #endif // FML_OS_IOS_SIMULATOR
499 if (runCheck && shouldResubmitFrame) {
504 - (void)pushFilterToVisitedPlatformViews:(const std::shared_ptr<
flutter::DlImageFilter>&)filter
505 withRect:(const SkRect&)filterRect {
506 for (int64_t
id :
self.visitedPlatformViews) {
507 flutter::EmbeddedViewParams params =
self.currentCompositionParams[id];
508 params.PushImageFilter(filter, filterRect);
509 self.currentCompositionParams[id] = params;
513 - (void)prerollCompositeEmbeddedView:(int64_t)viewId
514 withParams:(std::unique_ptr<
flutter::EmbeddedViewParams>)params {
515 SkRect viewBounds = SkRect::Make(
self.frameSize);
516 std::unique_ptr<flutter::EmbedderViewSlice> view;
517 view = std::make_unique<flutter::DisplayListEmbedderViewSlice>(viewBounds);
518 self.slices.insert_or_assign(viewId, std::move(view));
520 self.compositionOrder.push_back(viewId);
522 if (
self.currentCompositionParams.count(viewId) == 1 &&
523 self.currentCompositionParams[viewId] == *params.get()) {
527 self.currentCompositionParams[viewId] = flutter::EmbeddedViewParams(*params.get());
528 self.viewsToRecomposite.insert(viewId);
531 - (size_t)embeddedViewCount {
532 return self.compositionOrder.size();
535 - (UIView*)platformViewForId:(int64_t)viewId {
536 return [
self flutterTouchInterceptingViewForId:viewId].embeddedView;
540 if (
self.platformViews.empty()) {
543 return self.platformViews[viewId].touch_interceptor;
546 - (long)firstResponderPlatformViewId {
547 for (
auto const& [
id, platformViewData] :
self.platformViews) {
548 UIView* rootView = platformViewData.root_view;
549 if (rootView.flt_hasFirstResponderInViewHierarchySubtree) {
556 - (void)clipViewSetMaskView:(UIView*)clipView {
557 FML_DCHECK([[NSThread currentThread] isMainThread]);
558 if (clipView.maskView) {
562 CGRectMake(-clipView.frame.origin.x, -clipView.frame.origin.y,
563 CGRectGetWidth(
self.flutterView.bounds), CGRectGetHeight(
self.flutterView.bounds));
564 clipView.maskView = [
self.maskViewPool getMaskViewWithFrame:frame];
567 - (void)applyMutators:(const
flutter::MutatorsStack&)mutatorsStack
568 embeddedView:(UIView*)embeddedView
569 boundingRect:(const SkRect&)boundingRect {
570 if (
self.flutterView == nil) {
577 SkMatrix transformMatrix;
578 NSMutableArray* blurFilters = [[NSMutableArray alloc] init];
579 FML_DCHECK(!clipView.maskView ||
581 if (clipView.maskView) {
582 [
self.maskViewPool insertViewToPoolIfNeeded:(FlutterClippingMaskView*)(clipView.maskView)];
583 clipView.maskView = nil;
585 CGFloat screenScale = [UIScreen mainScreen].scale;
586 auto iter = mutatorsStack.Begin();
587 while (iter != mutatorsStack.End()) {
588 switch ((*iter)->GetType()) {
589 case flutter::kTransform: {
590 transformMatrix.preConcat((*iter)->GetMatrix());
593 case flutter::kClipRect: {
598 [
self clipViewSetMaskView:clipView];
600 matrix:transformMatrix];
603 case flutter::kClipRRect: {
608 [
self clipViewSetMaskView:clipView];
610 matrix:transformMatrix];
613 case flutter::kClipPath: {
617 [
self clipViewSetMaskView:clipView];
619 matrix:transformMatrix];
622 case flutter::kOpacity:
623 embeddedView.alpha = (*iter)->GetAlphaFloat() * embeddedView.alpha;
625 case flutter::kBackdropFilter: {
627 if (!
self.canApplyBlurBackdrop || !(*iter)->GetFilterMutation().GetFilter().asBlur()) {
632 filterRect = CGRectApplyAffineTransform(
633 filterRect, CGAffineTransformMakeScale(1 / screenScale, 1 / screenScale));
637 if (CGRectIsNull(CGRectIntersection(filterRect, clipView.frame))) {
640 CGRect intersection = CGRectIntersection(filterRect, clipView.frame);
641 CGRect frameInClipView = [
self.flutterView convertRect:intersection toView:clipView];
646 CGFloat blurRadius = (*iter)->GetFilterMutation().GetFilter().asBlur()->sigma_x();
647 UIVisualEffectView* visualEffectView = [[UIVisualEffectView alloc]
648 initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
650 blurRadius:blurRadius
651 visualEffectView:visualEffectView];
653 self.canApplyBlurBackdrop = NO;
655 [blurFilters addObject:filter];
663 if (
self.canApplyBlurBackdrop) {
672 transformMatrix.postScale(1 / screenScale, 1 / screenScale);
681 transformMatrix.postTranslate(-clipView.frame.origin.x, -clipView.frame.origin.y);
686 - (void)compositeView:(int64_t)viewId withParams:(const
flutter::EmbeddedViewParams&)params {
688 CGRect frame = CGRectMake(0, 0, params.sizePoints().width(), params.sizePoints().height());
690 touchInterceptor.layer.transform = CATransform3DIdentity;
691 touchInterceptor.frame = frame;
692 touchInterceptor.alpha = 1;
694 const flutter::MutatorsStack& mutatorStack = params.mutatorsStack();
695 UIView* clippingView =
self.platformViews[viewId].root_view;
700 const SkRect& rect = params.finalBoundingRect();
701 CGFloat screenScale = [UIScreen mainScreen].scale;
702 clippingView.frame = CGRectMake(rect.x() / screenScale, rect.y() / screenScale,
703 rect.width() / screenScale, rect.height() / screenScale);
704 [
self applyMutators:mutatorStack embeddedView:touchInterceptor boundingRect:rect];
707 - (
flutter::DlCanvas*)compositeEmbeddedViewWithId:(int64_t)viewId {
708 FML_DCHECK(
self.slices.find(viewId) !=
self.slices.end());
709 return self.slices[viewId]->canvas();
716 fml::TaskRunner::RunNowOrPostTask(
self.platformTaskRunner, [
self]() {
717 for (int64_t viewId :
self.compositionOrder) {
718 [
self.platformViews[viewId].root_view removeFromSuperview];
720 self.platformViews.clear();
723 self.compositionOrder.clear();
725 self.currentCompositionParams.clear();
726 self.viewsToRecomposite.clear();
727 self.layerPool->RecycleLayers();
728 self.visitedPlatformViews.clear();
731 - (BOOL)submitFrame:(std::unique_ptr<
flutter::SurfaceFrame>)background_frame
732 withIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext
733 grContext:(GrDirectContext*)grContext {
734 TRACE_EVENT0(
"flutter",
"PlatformViewsController::SubmitFrame");
737 if (
self.flutterView == nil || (
self.compositionOrder.empty() && !
self.hadPlatformViews)) {
738 self.hadPlatformViews = NO;
739 return background_frame->Submit();
741 self.hadPlatformViews = !
self.compositionOrder.empty();
743 bool didEncode =
true;
745 std::vector<std::unique_ptr<flutter::SurfaceFrame>> surfaceFrames;
746 surfaceFrames.reserve(
self.compositionOrder.size());
747 std::unordered_map<int64_t, SkRect> viewRects;
749 for (int64_t viewId :
self.compositionOrder) {
750 viewRects[viewId] =
self.currentCompositionParams[viewId].finalBoundingRect();
753 std::unordered_map<int64_t, SkRect> overlayLayers =
754 SliceViews(background_frame->Canvas(),
self.compositionOrder,
self.slices, viewRects);
756 size_t requiredOverlayLayers = 0;
757 for (int64_t viewId :
self.compositionOrder) {
758 std::unordered_map<int64_t, SkRect>::const_iterator overlay = overlayLayers.find(viewId);
759 if (overlay == overlayLayers.end()) {
762 requiredOverlayLayers++;
768 [
self createMissingOverlays:requiredOverlayLayers withIosContext:iosContext grContext:grContext];
770 int64_t overlayId = 0;
771 for (int64_t viewId :
self.compositionOrder) {
772 std::unordered_map<int64_t, SkRect>::const_iterator overlay = overlayLayers.find(viewId);
773 if (overlay == overlayLayers.end()) {
776 std::shared_ptr<flutter::OverlayLayer> layer =
self.nextLayerInPool;
781 std::unique_ptr<flutter::SurfaceFrame> frame = layer->surface->AcquireFrame(
self.frameSize);
786 flutter::DlCanvas* overlayCanvas = frame->Canvas();
787 int restoreCount = overlayCanvas->GetSaveCount();
788 overlayCanvas->Save();
789 overlayCanvas->ClipRect(overlay->second);
790 overlayCanvas->Clear(flutter::DlColor::kTransparent());
791 self.slices[viewId]->render_into(overlayCanvas);
792 overlayCanvas->RestoreToCount(restoreCount);
796 frame->set_submit_info({.frame_boundary =
false, .present_with_transaction =
true});
797 layer->did_submit_last_frame = frame->Encode();
799 didEncode &= layer->did_submit_last_frame;
801 .
rect = overlay->second,
803 .overlay_id = overlayId,
806 surfaceFrames.push_back(std::move(frame));
810 auto previousSubmitInfo = background_frame->submit_info();
811 background_frame->set_submit_info({
812 .frame_damage = previousSubmitInfo.frame_damage,
813 .buffer_damage = previousSubmitInfo.buffer_damage,
814 .present_with_transaction =
true,
816 background_frame->Encode();
817 surfaceFrames.push_back(std::move(background_frame));
820 std::vector<std::shared_ptr<flutter::OverlayLayer>> unusedLayers =
821 self.layerPool->RemoveUnusedLayers();
822 self.layerPool->RecycleLayers();
825 platformViewLayers = std::move(platformViewLayers),
826 currentCompositionParams = self.currentCompositionParams,
827 viewsToRecomposite = self.viewsToRecomposite,
828 compositionOrder = self.compositionOrder,
829 unusedLayers = std::move(unusedLayers),
830 surfaceFrames = std::move(surfaceFrames)
832 [
self performSubmit:platformViewLayers
833 currentCompositionParams:currentCompositionParams
834 viewsToRecomposite:viewsToRecomposite
835 compositionOrder:compositionOrder
836 unusedLayers:unusedLayers
837 surfaceFrames:surfaceFrames];
840 fml::TaskRunner::RunNowOrPostTask(
self.platformTaskRunner, fml::MakeCopyable(std::move(task)));
845 - (void)createMissingOverlays:(
size_t)requiredOverlayLayers
846 withIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext
847 grContext:(GrDirectContext*)grContext {
848 TRACE_EVENT0(
"flutter",
"PlatformViewsController::CreateMissingLayers");
850 if (requiredOverlayLayers <= self.layerPool->size()) {
853 auto missingLayerCount = requiredOverlayLayers -
self.layerPool->size();
857 auto latch = std::make_shared<fml::CountDownLatch>(1u);
858 fml::TaskRunner::RunNowOrPostTask(
859 self.platformTaskRunner, [
self, missingLayerCount, iosContext, grContext, latch]() {
860 for (
auto i = 0u; i < missingLayerCount; i++) {
861 [
self createLayerWithIosContext:iosContext
863 pixelFormat:((FlutterView*)self.flutterView).pixelFormat];
867 if (![[NSThread currentThread] isMainThread]) {
872 - (void)performSubmit:(const
LayersMap&)platformViewLayers
873 currentCompositionParams:
874 (std::unordered_map<int64_t,
flutter::EmbeddedViewParams>&)currentCompositionParams
875 viewsToRecomposite:(const std::unordered_set<int64_t>&)viewsToRecomposite
876 compositionOrder:(const std::vector<int64_t>&)compositionOrder
878 (const std::vector<std::shared_ptr<
flutter::OverlayLayer>>&)unusedLayers
880 (const std::vector<std::unique_ptr<
flutter::SurfaceFrame>>&)surfaceFrames {
881 TRACE_EVENT0(
"flutter",
"PlatformViewsController::PerformSubmit");
882 FML_DCHECK([[NSThread currentThread] isMainThread]);
884 [CATransaction begin];
887 for (
const auto& [viewId, layerData] : platformViewLayers) {
888 layerData.layer->UpdateViewState(
self.flutterView,
896 for (
auto& view : [
self computeViewsToDispose]) {
897 [view removeFromSuperview];
901 for (int64_t viewId : viewsToRecomposite) {
902 [
self compositeView:viewId withParams:currentCompositionParams[viewId]];
906 for (
const auto& frame : surfaceFrames) {
912 [
self removeUnusedLayers:unusedLayers withCompositionOrder:compositionOrder];
915 [
self bringLayersIntoView:platformViewLayers withCompositionOrder:compositionOrder];
917 [CATransaction commit];
920 - (void)bringLayersIntoView:(const
LayersMap&)layerMap
921 withCompositionOrder:(const std::vector<int64_t>&)compositionOrder {
922 FML_DCHECK(
self.flutterView);
923 UIView* flutterView =
self.flutterView;
925 self.previousCompositionOrder.clear();
926 NSMutableArray* desiredPlatformSubviews = [NSMutableArray array];
927 for (int64_t platformViewId : compositionOrder) {
928 self.previousCompositionOrder.push_back(platformViewId);
929 UIView* platformViewRoot =
self.platformViews[platformViewId].root_view;
930 if (platformViewRoot != nil) {
931 [desiredPlatformSubviews addObject:platformViewRoot];
934 auto maybeLayerData = layerMap.find(platformViewId);
935 if (maybeLayerData != layerMap.end()) {
936 auto view = maybeLayerData->second.layer->overlay_view_wrapper;
938 [desiredPlatformSubviews addObject:view];
943 NSSet* desiredPlatformSubviewsSet = [NSSet setWithArray:desiredPlatformSubviews];
944 NSArray* existingPlatformSubviews = [flutterView.subviews
945 filteredArrayUsingPredicate:[NSPredicate
946 predicateWithBlock:^BOOL(id object, NSDictionary* bindings) {
947 return [desiredPlatformSubviewsSet containsObject:object];
954 if (![desiredPlatformSubviews isEqualToArray:existingPlatformSubviews]) {
955 for (UIView* subview in desiredPlatformSubviews) {
957 [flutterView addSubview:subview];
962 - (std::shared_ptr<flutter::OverlayLayer>)nextLayerInPool {
963 return self.layerPool->GetNextLayer();
966 - (void)createLayerWithIosContext:(const std::shared_ptr<
flutter::IOSContext>&)iosContext
967 grContext:(GrDirectContext*)grContext
968 pixelFormat:(MTLPixelFormat)pixelFormat {
969 self.layerPool->CreateLayer(grContext, iosContext, pixelFormat);
972 - (void)removeUnusedLayers:(const std::vector<std::shared_ptr<
flutter::OverlayLayer>>&)unusedLayers
973 withCompositionOrder:(const std::vector<int64_t>&)compositionOrder {
974 for (
const std::shared_ptr<flutter::OverlayLayer>& layer : unusedLayers) {
975 [layer->overlay_view_wrapper removeFromSuperview];
978 std::unordered_set<int64_t> compositionOrderSet;
979 for (int64_t viewId : compositionOrder) {
980 compositionOrderSet.insert(viewId);
983 for (int64_t viewId :
self.previousCompositionOrder) {
984 if (compositionOrderSet.find(viewId) == compositionOrderSet.end()) {
985 UIView* platformViewRoot =
self.platformViews[viewId].root_view;
986 [platformViewRoot removeFromSuperview];
991 - (std::vector<UIView*>)computeViewsToDispose {
992 std::vector<UIView*> views;
993 if (
self.viewsToDispose.empty()) {
997 std::unordered_set<int64_t> viewsToComposite(
self.compositionOrder.begin(),
998 self.compositionOrder.end());
999 std::unordered_set<int64_t> viewsToDelayDispose;
1000 for (int64_t viewId :
self.viewsToDispose) {
1001 if (viewsToComposite.count(viewId)) {
1002 viewsToDelayDispose.insert(viewId);
1005 UIView* rootView =
self.platformViews[viewId].root_view;
1006 views.push_back(rootView);
1007 self.currentCompositionParams.erase(viewId);
1008 self.viewsToRecomposite.erase(viewId);
1009 self.platformViews.erase(viewId);
1011 self.viewsToDispose = std::move(viewsToDelayDispose);
1015 - (void)resetFrameState {
1016 self.slices.clear();
1017 self.compositionOrder.clear();
1018 self.visitedPlatformViews.clear();
1021 - (void)pushVisitedPlatformViewId:(int64_t)viewId {
1022 self.visitedPlatformViews.push_back(viewId);
1025 - (const
flutter::EmbeddedViewParams&)compositionParamsForView:(int64_t)viewId {
1026 return self.currentCompositionParams.find(viewId)->second;
1029 #pragma mark - Properties
1031 - (
flutter::OverlayLayerPool*)layerPool {
1032 return _layerPool.get();
1035 - (std::unordered_map<int64_t, std::unique_ptr<flutter::EmbedderViewSlice>>&)slices {
1039 - (std::unordered_map<std::string, NSObject<FlutterPlatformViewFactory>*>&)factories {
1042 - (std::unordered_map<std::string, FlutterPlatformViewGestureRecognizersBlockingPolicy>&)
1043 gestureRecognizersBlockingPolicies {
1047 - (std::unordered_map<int64_t, PlatformViewData>&)platformViews {
1051 - (std::unordered_map<int64_t, flutter::EmbeddedViewParams>&)currentCompositionParams {
1055 - (std::unordered_set<int64_t>&)viewsToDispose {
1059 - (std::vector<int64_t>&)compositionOrder {
1063 - (std::vector<int64_t>&)visitedPlatformViews {
1067 - (std::unordered_set<int64_t>&)viewsToRecomposite {
1071 - (std::vector<int64_t>&)previousCompositionOrder {