diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 3493f02be7415..ddc2153ec6e30 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -287,16 +287,16 @@ class ExternalViewEmbedder { virtual bool SubmitFrame(GrContext* context, std::unique_ptr frame); - // This should only be called after |SubmitFrame|. // This method provides the embedder a way to do additional tasks after - // |SubmitFrame|. After invoking this method, the current task on the - // TaskRunner should end immediately. + // |SubmitFrame|. For example, merge task runners if `should_resubmit_frame` + // is true. // // For example on the iOS embedder, threads are merged in this call. // A new frame on the platform thread starts immediately. If the GPU thread // still has some task running, there could be two frames being rendered // concurrently, which causes undefined behaviors. virtual void EndFrame( + bool should_resubmit_frame, fml::RefPtr raster_thread_merger) {} FML_DISALLOW_COPY_AND_ASSIGN(ExternalViewEmbedder); diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index afcce2960a6a6..ca69a7b2abdf5 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -151,12 +151,10 @@ void Rasterizer::Draw(fml::RefPtr> pipeline) { // Merging the thread as we know the next `Draw` should be run on the platform // thread. - if (raster_status == RasterStatus::kResubmit) { - auto* external_view_embedder = surface_->GetExternalViewEmbedder(); - // We know only the `external_view_embedder` can - // causes|RasterStatus::kResubmit|. Check to make sure. - FML_DCHECK(external_view_embedder != nullptr); - external_view_embedder->EndFrame(raster_thread_merger_); + if (surface_ != nullptr && surface_->GetExternalViewEmbedder() != nullptr) { + auto should_resubmit_frame = raster_status == RasterStatus::kResubmit; + surface_->GetExternalViewEmbedder()->EndFrame(should_resubmit_frame, + raster_thread_merger_); } // Consume as many pipeline items as possible. But yield the event loop diff --git a/shell/common/shell_test_external_view_embedder.cc b/shell/common/shell_test_external_view_embedder.cc index 306c1b0016b44..ba7aa22cb22f9 100644 --- a/shell/common/shell_test_external_view_embedder.cc +++ b/shell/common/shell_test_external_view_embedder.cc @@ -43,8 +43,9 @@ bool ShellTestExternalViewEmbedder::SubmitFrame( // |ExternalViewEmbedder| void ShellTestExternalViewEmbedder::EndFrame( + bool should_resubmit_frame, fml::RefPtr raster_thread_merger) { - end_frame_call_back_(); + end_frame_call_back_(should_resubmit_frame); } // |ExternalViewEmbedder| diff --git a/shell/common/shell_test_external_view_embedder.h b/shell/common/shell_test_external_view_embedder.h index da96503a9bb46..26072331eae39 100644 --- a/shell/common/shell_test_external_view_embedder.h +++ b/shell/common/shell_test_external_view_embedder.h @@ -15,7 +15,7 @@ namespace flutter { /// class ShellTestExternalViewEmbedder final : public ExternalViewEmbedder { public: - using EndFrameCallBack = std::function; + using EndFrameCallBack = std::function; ShellTestExternalViewEmbedder(const EndFrameCallBack& end_frame_call_back, PostPrerollResult post_preroll_result) @@ -56,6 +56,7 @@ class ShellTestExternalViewEmbedder final : public ExternalViewEmbedder { // |ExternalViewEmbedder| void EndFrame( + bool should_resubmit_frame, fml::RefPtr raster_thread_merger) override; // |ExternalViewEmbedder| diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc index 9b3da6833f60d..b9ba1e09dd1b5 100644 --- a/shell/common/shell_unittests.cc +++ b/shell/common/shell_unittests.cc @@ -474,7 +474,8 @@ TEST_F(ShellTest, auto settings = CreateSettingsForFixture(); fml::AutoResetWaitableEvent endFrameLatch; bool end_frame_called = false; - auto end_frame_callback = [&] { + auto end_frame_callback = [&](bool should_resubmit_frame) { + ASSERT_TRUE(should_resubmit_frame); end_frame_called = true; endFrameLatch.Signal(); }; diff --git a/shell/platform/android/external_view_embedder/external_view_embedder.cc b/shell/platform/android/external_view_embedder/external_view_embedder.cc index f1f46ab21b49c..f2c9947c419ce 100644 --- a/shell/platform/android/external_view_embedder/external_view_embedder.cc +++ b/shell/platform/android/external_view_embedder/external_view_embedder.cc @@ -255,8 +255,9 @@ void AndroidExternalViewEmbedder::CancelFrame() { // |ExternalViewEmbedder| void AndroidExternalViewEmbedder::EndFrame( + bool should_resubmit_frame, fml::RefPtr raster_thread_merger) { - if (should_run_rasterizer_on_platform_thread_) { + if (should_resubmit_frame && should_run_rasterizer_on_platform_thread_) { raster_thread_merger->MergeWithLease(kDefaultMergedLeaseDuration); should_run_rasterizer_on_platform_thread_ = false; } diff --git a/shell/platform/android/external_view_embedder/external_view_embedder.h b/shell/platform/android/external_view_embedder/external_view_embedder.h index 41b6e68f1155d..2f0562bdbf685 100644 --- a/shell/platform/android/external_view_embedder/external_view_embedder.h +++ b/shell/platform/android/external_view_embedder/external_view_embedder.h @@ -65,6 +65,7 @@ class AndroidExternalViewEmbedder final : public ExternalViewEmbedder { // |ExternalViewEmbedder| void EndFrame( + bool should_resubmit_frame, fml::RefPtr raster_thread_merger) override; // Gets the rect based on the device pixel ratio of a platform view displayed diff --git a/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc b/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc index a0551a0a39dea..8bac045e1b906 100644 --- a/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc +++ b/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc @@ -158,7 +158,7 @@ TEST(AndroidExternalViewEmbedder, RasterizerRunsOnPlatformThread) { ASSERT_TRUE(embedder->SubmitFrame(nullptr, nullptr)); EXPECT_CALL(*jni_mock, FlutterViewEndFrame()); - embedder->EndFrame(raster_thread_merger); + embedder->EndFrame(/*should_resubmit_frame=*/true, raster_thread_merger); ASSERT_TRUE(raster_thread_merger->IsMerged()); @@ -182,7 +182,7 @@ TEST(AndroidExternalViewEmbedder, RasterizerRunsOnRasterizerThread) { ASSERT_EQ(PostPrerollResult::kSuccess, result); EXPECT_CALL(*jni_mock, FlutterViewEndFrame()); - embedder->EndFrame(raster_thread_merger); + embedder->EndFrame(/*should_resubmit_frame=*/true, raster_thread_merger); ASSERT_FALSE(raster_thread_merger->IsMerged()); } @@ -332,7 +332,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame__RecycleSurfaces) { embedder->SubmitFrame(gr_context.get(), std::move(surface_frame)); EXPECT_CALL(*jni_mock, FlutterViewEndFrame()); - embedder->EndFrame(raster_thread_merger); + embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger); } // ------------------ Second frame ------------------ // @@ -380,7 +380,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame__RecycleSurfaces) { embedder->SubmitFrame(gr_context.get(), std::move(surface_frame)); EXPECT_CALL(*jni_mock, FlutterViewEndFrame()); - embedder->EndFrame(raster_thread_merger); + embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger); } } @@ -399,7 +399,7 @@ TEST(AndroidExternalViewEmbedder, DoesNotCallJNIPlatformThreadOnlyMethods) { raster_thread_merger); EXPECT_CALL(*jni_mock, FlutterViewEndFrame()).Times(0); - embedder->EndFrame(raster_thread_merger); + embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger); } } // namespace testing diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 474e9f084c1ee..1b021bc60818d 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -604,8 +604,9 @@ } void FlutterPlatformViewsController::EndFrame( + bool should_resubmit_frame, fml::RefPtr raster_thread_merger) { - if (merge_threads_) { + if (should_resubmit_frame && merge_threads_) { raster_thread_merger->MergeWithLease(kDefaultMergedLeaseDuration); merge_threads_ = false; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index 26984400c2ef2..8c570cd97cb96 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -168,7 +168,8 @@ class FlutterPlatformViewsController { // Invoked at the very end of a frame. // After invoking this method, nothing should happen on the current TaskRunner during the same // frame. - void EndFrame(fml::RefPtr raster_thread_merger); + void EndFrame(bool should_resubmit_frame, + fml::RefPtr raster_thread_merger); void OnMethodCall(FlutterMethodCall* call, FlutterResult& result); diff --git a/shell/platform/darwin/ios/ios_surface.h b/shell/platform/darwin/ios/ios_surface.h index 5fb6f78f6d7cc..5e58ce2c6af4e 100644 --- a/shell/platform/darwin/ios/ios_surface.h +++ b/shell/platform/darwin/ios/ios_surface.h @@ -85,7 +85,8 @@ class IOSSurface : public ExternalViewEmbedder { bool SubmitFrame(GrContext* context, std::unique_ptr frame) override; // |ExternalViewEmbedder| - void EndFrame(fml::RefPtr raster_thread_merger) override; + void EndFrame(bool should_resubmit_frame, + fml::RefPtr raster_thread_merger) override; public: FML_DISALLOW_COPY_AND_ASSIGN(IOSSurface); diff --git a/shell/platform/darwin/ios/ios_surface.mm b/shell/platform/darwin/ios/ios_surface.mm index 26eca6cf26b90..30b08c298c5b9 100644 --- a/shell/platform/darwin/ios/ios_surface.mm +++ b/shell/platform/darwin/ios/ios_surface.mm @@ -149,10 +149,11 @@ bool IsIosEmbeddedViewsPreviewEnabled() { } // |ExternalViewEmbedder| -void IOSSurface::EndFrame(fml::RefPtr raster_thread_merger) { +void IOSSurface::EndFrame(bool should_resubmit_frame, + fml::RefPtr raster_thread_merger) { TRACE_EVENT0("flutter", "IOSSurface::EndFrame"); FML_CHECK(platform_views_controller_ != nullptr); - return platform_views_controller_->EndFrame(raster_thread_merger); + return platform_views_controller_->EndFrame(should_resubmit_frame, raster_thread_merger); } } // namespace flutter