diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index 07a484999ff51..9441c8dc9470c 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -60,4 +60,8 @@ const std::vector>::const_iterator MutatorsStack::End() return vector_.end(); }; +bool ExternalViewEmbedder::SupportsDynamicThreadMerging() { + return false; +} + } // namespace flutter diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 455eb91511801..cbfde228786a3 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -266,6 +266,10 @@ class ExternalViewEmbedder { // sets the stage for the next pre-roll. virtual void CancelFrame() = 0; + // Indicates the begining of a frame. + // + // The `raster_thread_merger` will be null if |SupportsDynamicThreadMerging| + // returns false. virtual void BeginFrame( SkISize frame_size, GrDirectContext* context, @@ -306,10 +310,20 @@ class ExternalViewEmbedder { // 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. + // + // The `raster_thread_merger` will be null if |SupportsDynamicThreadMerging| + // returns false. virtual void EndFrame( bool should_resubmit_frame, fml::RefPtr raster_thread_merger) {} + // Whether the embedder should support dynamic thread merging. + // + // Returning `true` results a |RasterThreadMerger| instance to be created. + // * See also |BegineFrame| and |EndFrame| for getting the + // |RasterThreadMerger| instance. + virtual bool SupportsDynamicThreadMerging(); + FML_DISALLOW_COPY_AND_ASSIGN(ExternalViewEmbedder); }; // ExternalViewEmbedder diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 709d5495ba626..0cdaa6a80415a 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -81,7 +81,8 @@ void Rasterizer::Setup(std::unique_ptr surface) { #if !defined(OS_FUCHSIA) // TODO(sanjayc77): https://github.com/flutter/flutter/issues/53179. Add // support for raster thread merger for Fuchsia. - if (surface_->GetExternalViewEmbedder()) { + if (surface_->GetExternalViewEmbedder() && + surface_->GetExternalViewEmbedder()->SupportsDynamicThreadMerging()) { const auto platform_id = task_runners_.GetPlatformTaskRunner()->GetTaskQueueId(); const auto gpu_id = task_runners_.GetRasterTaskRunner()->GetTaskQueueId(); diff --git a/shell/common/shell_test_external_view_embedder.cc b/shell/common/shell_test_external_view_embedder.cc index f3a5a0a37d27d..105f109dbab31 100644 --- a/shell/common/shell_test_external_view_embedder.cc +++ b/shell/common/shell_test_external_view_embedder.cc @@ -45,7 +45,7 @@ void ShellTestExternalViewEmbedder::SubmitFrame( void ShellTestExternalViewEmbedder::EndFrame( bool should_resubmit_frame, fml::RefPtr raster_thread_merger) { - end_frame_call_back_(should_resubmit_frame); + end_frame_call_back_(should_resubmit_frame, raster_thread_merger); } // |ExternalViewEmbedder| @@ -53,4 +53,8 @@ SkCanvas* ShellTestExternalViewEmbedder::GetRootCanvas() { return nullptr; } +bool ShellTestExternalViewEmbedder::SupportsDynamicThreadMerging() { + return support_thread_merging_; +} + } // namespace flutter diff --git a/shell/common/shell_test_external_view_embedder.h b/shell/common/shell_test_external_view_embedder.h index c67772df74f9a..8b855a0a7f4f6 100644 --- a/shell/common/shell_test_external_view_embedder.h +++ b/shell/common/shell_test_external_view_embedder.h @@ -15,12 +15,15 @@ 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) + PostPrerollResult post_preroll_result, + bool support_thread_merging) : end_frame_call_back_(end_frame_call_back), - post_preroll_result_(post_preroll_result) {} + post_preroll_result_(post_preroll_result), + support_thread_merging_(support_thread_merging) {} ~ShellTestExternalViewEmbedder() = default; @@ -62,9 +65,14 @@ class ShellTestExternalViewEmbedder final : public ExternalViewEmbedder { // |ExternalViewEmbedder| SkCanvas* GetRootCanvas() override; + // |ExternalViewEmbedder| + bool SupportsDynamicThreadMerging() override; + const EndFrameCallBack end_frame_call_back_; const PostPrerollResult post_preroll_result_; + bool support_thread_merging_; + FML_DISALLOW_COPY_AND_ASSIGN(ShellTestExternalViewEmbedder); }; diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc index d1ce6ecfbaf0d..68dc10f59cd4a 100644 --- a/shell/common/shell_unittests.cc +++ b/shell/common/shell_unittests.cc @@ -478,18 +478,69 @@ TEST_F(ShellTest, FrameRasterizedCallbackIsCalled) { #if !defined(OS_FUCHSIA) // TODO(sanjayc77): https://github.com/flutter/flutter/issues/53179. Add // support for raster thread merger for Fuchsia. +TEST_F(ShellTest, ExternalEmbedderNoThreadMerger) { + auto settings = CreateSettingsForFixture(); + fml::AutoResetWaitableEvent endFrameLatch; + bool end_frame_called = false; + auto end_frame_callback = + [&](bool should_resubmit_frame, + fml::RefPtr raster_thread_merger) { + ASSERT_TRUE(raster_thread_merger.get() == nullptr); + ASSERT_FALSE(should_resubmit_frame); + end_frame_called = true; + endFrameLatch.Signal(); + }; + auto external_view_embedder = std::make_shared( + end_frame_callback, PostPrerollResult::kResubmitFrame, false); + auto shell = CreateShell(std::move(settings), GetTaskRunnersForFixture(), + false, external_view_embedder); + + // Create the surface needed by rasterizer + PlatformViewNotifyCreated(shell.get()); + + auto configuration = RunConfiguration::InferFromSettings(settings); + configuration.SetEntrypoint("emptyMain"); + + RunEngine(shell.get(), std::move(configuration)); + + LayerTreeBuilder builder = [&](std::shared_ptr root) { + SkPictureRecorder recorder; + SkCanvas* recording_canvas = + recorder.beginRecording(SkRect::MakeXYWH(0, 0, 80, 80)); + recording_canvas->drawRect(SkRect::MakeXYWH(0, 0, 80, 80), + SkPaint(SkColor4f::FromColor(SK_ColorRED))); + auto sk_picture = recorder.finishRecordingAsPicture(); + fml::RefPtr queue = fml::MakeRefCounted( + this->GetCurrentTaskRunner(), fml::TimeDelta::FromSeconds(0)); + auto picture_layer = std::make_shared( + SkPoint::Make(10, 10), + flutter::SkiaGPUObject({sk_picture, queue}), false, false); + root->Add(picture_layer); + }; + + PumpOneFrame(shell.get(), 100, 100, builder); + endFrameLatch.Wait(); + + ASSERT_TRUE(end_frame_called); + + DestroyShell(std::move(shell)); +} + TEST_F(ShellTest, ExternalEmbedderEndFrameIsCalledWhenPostPrerollResultIsResubmit) { auto settings = CreateSettingsForFixture(); fml::AutoResetWaitableEvent endFrameLatch; bool end_frame_called = false; - auto end_frame_callback = [&](bool should_resubmit_frame) { - ASSERT_TRUE(should_resubmit_frame); - end_frame_called = true; - endFrameLatch.Signal(); - }; + auto end_frame_callback = + [&](bool should_resubmit_frame, + fml::RefPtr raster_thread_merger) { + ASSERT_TRUE(raster_thread_merger.get() != nullptr); + ASSERT_TRUE(should_resubmit_frame); + end_frame_called = true; + endFrameLatch.Signal(); + }; auto external_view_embedder = std::make_shared( - end_frame_callback, PostPrerollResult::kResubmitFrame); + end_frame_callback, PostPrerollResult::kResubmitFrame, true); auto shell = CreateShell(std::move(settings), GetTaskRunnersForFixture(), false, external_view_embedder); 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 9a32dc171eabf..b5479284aa0ef 100644 --- a/shell/platform/android/external_view_embedder/external_view_embedder.cc +++ b/shell/platform/android/external_view_embedder/external_view_embedder.cc @@ -295,4 +295,9 @@ void AndroidExternalViewEmbedder::EndFrame( } } +// |ExternalViewEmbedder| +bool AndroidExternalViewEmbedder::SupportsDynamicThreadMerging() { + return true; +} + } // namespace flutter 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 9e827b83b0ee0..ce755f252a8ac 100644 --- a/shell/platform/android/external_view_embedder/external_view_embedder.h +++ b/shell/platform/android/external_view_embedder/external_view_embedder.h @@ -70,6 +70,8 @@ class AndroidExternalViewEmbedder final : public ExternalViewEmbedder { bool should_resubmit_frame, fml::RefPtr raster_thread_merger) override; + bool SupportsDynamicThreadMerging() override; + // Gets the rect based on the device pixel ratio of a platform view displayed // on the screen. SkRect GetViewRect(int view_id) const; 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 93356347ae322..bdb8ca1c6c286 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 @@ -556,5 +556,13 @@ TEST(AndroidExternalViewEmbedder, DestroyOverlayLayersOnSizeChange) { raster_thread_merger); } +TEST(AndroidExternalViewEmbedder, SupportsDynamicThreadMerging) { + auto jni_mock = std::make_shared(); + + auto embedder = + std::make_unique(nullptr, jni_mock, nullptr); + ASSERT_TRUE(embedder->SupportsDynamicThreadMerging()); +} + } // namespace testing } // namespace flutter diff --git a/shell/platform/darwin/ios/ios_surface.h b/shell/platform/darwin/ios/ios_surface.h index 041e3bacedb32..d5dfca5526c51 100644 --- a/shell/platform/darwin/ios/ios_surface.h +++ b/shell/platform/darwin/ios/ios_surface.h @@ -88,6 +88,9 @@ class IOSSurface : public ExternalViewEmbedder { void EndFrame(bool should_resubmit_frame, fml::RefPtr raster_thread_merger) override; + // |ExternalViewEmbedder| + bool SupportsDynamicThreadMerging() 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 de330fb58fc42..30327582a2599 100644 --- a/shell/platform/darwin/ios/ios_surface.mm +++ b/shell/platform/darwin/ios/ios_surface.mm @@ -155,4 +155,9 @@ bool IsIosEmbeddedViewsPreviewEnabled() { return platform_views_controller_->EndFrame(should_resubmit_frame, raster_thread_merger); } +// |ExternalViewEmbedder| +bool IOSSurface::SupportsDynamicThreadMerging() { + return true; +} + } // namespace flutter