diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 7f732f7b4fd4e..c0c185c6ee4b7 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -279,6 +279,11 @@ CancelFrame(); return PostPrerollResult::kSkipAndRetryFrame; } + // If the post preroll action is successful, we will display platform views in the current frame. + // In order to sync the rendering of the platform views (quartz) with skia's rendering, + // We need to begin an explicit CATransaction. This transaction needs to be submitted + // after the current frame is submitted. + BeginCATransaction(); raster_thread_merger->ExtendLeaseTo(kDefaultMergedLeaseDuration); return PostPrerollResult::kSuccess; } @@ -286,6 +291,9 @@ void FlutterPlatformViewsController::PrerollCompositeEmbeddedView( int view_id, std::unique_ptr params) { + // All the CATransactions should be committed by the end of the last frame, + // so catransaction_added_ must be false. + FML_DCHECK(!catransaction_added_); picture_recorders_[view_id] = std::make_unique(); auto rtree_factory = RTreeFactory(); @@ -548,6 +556,10 @@ did_submit &= frame->Submit(); + // If the frame is submitted with embedded platform views, + // there should be a |[CATransaction begin]| call in this frame prior to all the drawing. + // If that case, we need to commit the transaction. + CommitCATransactionIfNeeded(); return did_submit; } @@ -662,6 +674,21 @@ views_to_dispose_.clear(); } +void FlutterPlatformViewsController::BeginCATransaction() { + FML_DCHECK([[NSThread currentThread] isMainThread]); + FML_DCHECK(!catransaction_added_); + [CATransaction begin]; + catransaction_added_ = true; +} + +void FlutterPlatformViewsController::CommitCATransactionIfNeeded() { + if (catransaction_added_) { + FML_DCHECK([[NSThread currentThread] isMainThread]); + [CATransaction commit]; + catransaction_added_ = false; + } +} + } // namespace flutter // This recognizers delays touch events from being dispatched to the responder chain until it failed diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index f0867bc4bbcc8..4fcaaf3874212 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -245,6 +245,8 @@ class FlutterPlatformViewsController { std::unique_ptr> weak_factory_; + bool catransaction_added_ = false; + void OnCreate(FlutterMethodCall* call, FlutterResult& result); void OnDispose(FlutterMethodCall* call, FlutterResult& result); void OnAcceptGesture(FlutterMethodCall* call, FlutterResult& result); @@ -294,6 +296,13 @@ class FlutterPlatformViewsController { // order. void BringLayersIntoView(LayersMap layer_map); + // Begin a CATransaction. + // This transaction needs to be balanced with |CommitCATransactionIfNeeded|. + void BeginCATransaction(); + + // Commit a CATransaction if |BeginCATransaction| has been called during the frame. + void CommitCATransactionIfNeeded(); + FML_DISALLOW_COPY_AND_ASSIGN(FlutterPlatformViewsController); }; diff --git a/shell/platform/darwin/ios/ios_surface.mm b/shell/platform/darwin/ios/ios_surface.mm index 1583e0c41c6a3..976c71ee45a49 100644 --- a/shell/platform/darwin/ios/ios_surface.mm +++ b/shell/platform/darwin/ios/ios_surface.mm @@ -71,9 +71,6 @@ TRACE_EVENT0("flutter", "IOSSurface::CancelFrame"); FML_CHECK(platform_views_controller_ != nullptr); platform_views_controller_->CancelFrame(); - // Committing the current transaction as |BeginFrame| will create a nested - // CATransaction otherwise. - [CATransaction commit]; } // |ExternalViewEmbedder| @@ -84,7 +81,6 @@ TRACE_EVENT0("flutter", "IOSSurface::BeginFrame"); FML_CHECK(platform_views_controller_ != nullptr); platform_views_controller_->SetFrameSize(frame_size); - [CATransaction begin]; } // |ExternalViewEmbedder| @@ -102,10 +98,6 @@ TRACE_EVENT0("flutter", "IOSSurface::PostPrerollAction"); FML_CHECK(platform_views_controller_ != nullptr); PostPrerollResult result = platform_views_controller_->PostPrerollAction(raster_thread_merger); - if (result == PostPrerollResult::kSkipAndRetryFrame) { - // Commit the current transaction if the frame is dropped. - [CATransaction commit]; - } return result; } @@ -126,13 +118,8 @@ void IOSSurface::SubmitFrame(GrDirectContext* context, std::unique_ptr frame) { TRACE_EVENT0("flutter", "IOSSurface::SubmitFrame"); FML_CHECK(platform_views_controller_ != nullptr); - bool submitted = - platform_views_controller_->SubmitFrame(std::move(context), ios_context_, std::move(frame)); - - if (submitted) { - TRACE_EVENT0("flutter", "IOSSurface::DidSubmitFrame"); - [CATransaction commit]; - } + platform_views_controller_->SubmitFrame(std::move(context), ios_context_, std::move(frame)); + TRACE_EVENT0("flutter", "IOSSurface::DidSubmitFrame"); } // |ExternalViewEmbedder|