From e66a8fd6b708dca1d6d765bf17d69b139a46ba91 Mon Sep 17 00:00:00 2001 From: gaaclarke <30870216+gaaclarke@users.noreply.github.com> Date: Tue, 17 Nov 2020 18:43:01 -0800 Subject: [PATCH] started providing the GPU sync switch to external view embedders (#22302) --- flow/embedded_views.cc | 6 ++++-- flow/embedded_views.h | 7 +++++-- shell/common/rasterizer.cc | 5 +++-- shell/common/rasterizer_unittests.cc | 8 +++++--- .../shell_test_external_view_embedder.cc | 3 ++- .../shell_test_external_view_embedder.h | 6 ++++-- .../external_view_embedder.cc | 3 ++- .../external_view_embedder.h | 6 ++++-- .../external_view_embedder_unittests.cc | 10 +++++----- .../framework/Source/FlutterPlatformViews.mm | 19 ++++++++++++++++--- .../Source/FlutterPlatformViewsTest.mm | 12 ++++++++---- .../Source/FlutterPlatformViews_Internal.h | 7 ++++++- .../darwin/ios/ios_external_view_embedder.h | 6 ++++-- .../darwin/ios/ios_external_view_embedder.mm | 9 ++++++--- .../embedder_external_view_embedder.cc | 3 ++- .../embedder_external_view_embedder.h | 6 ++++-- .../flutter/fuchsia_external_view_embedder.cc | 3 ++- .../flutter/fuchsia_external_view_embedder.h | 6 ++++-- .../fuchsia/flutter/platform_view_unittest.cc | 4 +++- 19 files changed, 89 insertions(+), 40 deletions(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index 9441c8dc9470c..273006c8d5e1f 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -6,8 +6,10 @@ namespace flutter { -void ExternalViewEmbedder::SubmitFrame(GrDirectContext* context, - std::unique_ptr frame) { +void ExternalViewEmbedder::SubmitFrame( + GrDirectContext* context, + std::unique_ptr frame, + const std::shared_ptr& gpu_disable_sync_switch) { frame->Submit(); }; diff --git a/flow/embedded_views.h b/flow/embedded_views.h index e82d9e82c0471..4d6853a6c4489 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -10,6 +10,7 @@ #include "flutter/flow/surface_frame.h" #include "flutter/fml/memory/ref_counted.h" #include "flutter/fml/raster_thread_merger.h" +#include "flutter/fml/synchronization/sync_switch.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkPath.h" #include "third_party/skia/include/core/SkPoint.h" @@ -309,8 +310,10 @@ class ExternalViewEmbedder { // This method can mutate the root Skia canvas before submitting the frame. // // It can also allocate frames for overlay surfaces to compose hybrid views. - virtual void SubmitFrame(GrDirectContext* context, - std::unique_ptr frame); + virtual void SubmitFrame( + GrDirectContext* context, + std::unique_ptr frame, + const std::shared_ptr& gpu_disable_sync_switch); // This method provides the embedder a way to do additional tasks after // |SubmitFrame|. For example, merge task runners if `should_resubmit_frame` diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 1d326a7727166..3733e9586e8cc 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -469,8 +469,9 @@ RasterStatus Rasterizer::DrawToSurface(flutter::LayerTree& layer_tree) { if (external_view_embedder_ && (!raster_thread_merger_ || raster_thread_merger_->IsMerged())) { FML_DCHECK(!frame->IsSubmitted()); - external_view_embedder_->SubmitFrame(surface_->GetContext(), - std::move(frame)); + external_view_embedder_->SubmitFrame( + surface_->GetContext(), std::move(frame), + delegate_.GetIsGpuDisabledSyncSwitch()); } else { frame->Submit(); } diff --git a/shell/common/rasterizer_unittests.cc b/shell/common/rasterizer_unittests.cc index 38611b0343723..357a0f38e2da0 100644 --- a/shell/common/rasterizer_unittests.cc +++ b/shell/common/rasterizer_unittests.cc @@ -55,9 +55,11 @@ class MockExternalViewEmbedder : public ExternalViewEmbedder { fml::RefPtr raster_thread_merger)); MOCK_METHOD0(GetCurrentCanvases, std::vector()); MOCK_METHOD1(CompositeEmbeddedView, SkCanvas*(int view_id)); - MOCK_METHOD2(SubmitFrame, - void(GrDirectContext* context, - std::unique_ptr frame)); + MOCK_METHOD3( + SubmitFrame, + void(GrDirectContext* context, + std::unique_ptr frame, + const std::shared_ptr& gpu_disable_sync_switch)); MOCK_METHOD2(EndFrame, void(bool should_resubmit_frame, fml::RefPtr raster_thread_merger)); diff --git a/shell/common/shell_test_external_view_embedder.cc b/shell/common/shell_test_external_view_embedder.cc index 5a8edc19fb45a..80e82102629c7 100644 --- a/shell/common/shell_test_external_view_embedder.cc +++ b/shell/common/shell_test_external_view_embedder.cc @@ -63,7 +63,8 @@ SkCanvas* ShellTestExternalViewEmbedder::CompositeEmbeddedView(int view_id) { // |ExternalViewEmbedder| void ShellTestExternalViewEmbedder::SubmitFrame( GrDirectContext* context, - std::unique_ptr frame) { + std::unique_ptr frame, + const std::shared_ptr& gpu_disable_sync_switch) { frame->Submit(); if (frame && frame->SkiaSurface()) { last_submitted_frame_size_ = SkISize::Make(frame->SkiaSurface()->width(), diff --git a/shell/common/shell_test_external_view_embedder.h b/shell/common/shell_test_external_view_embedder.h index 72c101ed1f4bc..1782a035527a2 100644 --- a/shell/common/shell_test_external_view_embedder.h +++ b/shell/common/shell_test_external_view_embedder.h @@ -62,8 +62,10 @@ class ShellTestExternalViewEmbedder final : public ExternalViewEmbedder { SkCanvas* CompositeEmbeddedView(int view_id) override; // |ExternalViewEmbedder| - void SubmitFrame(GrDirectContext* context, - std::unique_ptr frame) override; + void SubmitFrame( + GrDirectContext* context, + std::unique_ptr frame, + const std::shared_ptr& gpu_disable_sync_switch) override; // |ExternalViewEmbedder| void EndFrame( 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 9e544d6a2e5f9..69370e7ca65bf 100644 --- a/shell/platform/android/external_view_embedder/external_view_embedder.cc +++ b/shell/platform/android/external_view_embedder/external_view_embedder.cc @@ -75,7 +75,8 @@ SkRect AndroidExternalViewEmbedder::GetViewRect(int view_id) const { // |ExternalViewEmbedder| void AndroidExternalViewEmbedder::SubmitFrame( GrDirectContext* context, - std::unique_ptr frame) { + std::unique_ptr frame, + const std::shared_ptr& gpu_disable_sync_switch) { TRACE_EVENT0("flutter", "AndroidExternalViewEmbedder::SubmitFrame"); if (!FrameHasPlatformLayers()) { 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 7398ce490aa7d..71d7e7c85c775 100644 --- a/shell/platform/android/external_view_embedder/external_view_embedder.h +++ b/shell/platform/android/external_view_embedder/external_view_embedder.h @@ -46,8 +46,10 @@ class AndroidExternalViewEmbedder final : public ExternalViewEmbedder { std::vector GetCurrentCanvases() override; // |ExternalViewEmbedder| - void SubmitFrame(GrDirectContext* context, - std::unique_ptr frame) override; + void SubmitFrame( + GrDirectContext* context, + std::unique_ptr frame, + const std::shared_ptr& gpu_disable_sync_switch) override; // |ExternalViewEmbedder| PostPrerollResult PostPrerollAction( 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 1c161cc953fae..3ea187ceacf76 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 @@ -331,7 +331,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) { return true; }); - embedder->SubmitFrame(gr_context.get(), std::move(surface_frame)); + embedder->SubmitFrame(gr_context.get(), std::move(surface_frame), nullptr); // Submits frame if no Android view in the current frame. EXPECT_TRUE(did_submit_frame); // Doesn't resubmit frame. @@ -398,7 +398,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) { return true; }); - embedder->SubmitFrame(gr_context.get(), std::move(surface_frame)); + embedder->SubmitFrame(gr_context.get(), std::move(surface_frame), nullptr); // Doesn't submit frame if there aren't Android views in the previous frame. EXPECT_FALSE(did_submit_frame); // Resubmits frame. @@ -462,7 +462,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) { } return true; }); - embedder->SubmitFrame(gr_context.get(), std::move(surface_frame)); + embedder->SubmitFrame(gr_context.get(), std::move(surface_frame), nullptr); // Submits frame if there are Android views in the previous frame. EXPECT_TRUE(did_submit_frame); // Doesn't resubmit frame. @@ -560,7 +560,7 @@ TEST(AndroidExternalViewEmbedder, DestroyOverlayLayersOnSizeChange) { std::make_unique(SkSurface::MakeNull(1000, 1000), false, [](const SurfaceFrame& surface_frame, SkCanvas* canvas) { return true; }); - embedder->SubmitFrame(gr_context.get(), std::move(surface_frame)); + embedder->SubmitFrame(gr_context.get(), std::move(surface_frame), nullptr); EXPECT_CALL(*jni_mock, FlutterViewEndFrame()); embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger); @@ -640,7 +640,7 @@ TEST(AndroidExternalViewEmbedder, DoesNotDestroyOverlayLayersOnSizeChange) { std::make_unique(SkSurface::MakeNull(1000, 1000), false, [](const SurfaceFrame& surface_frame, SkCanvas* canvas) { return true; }); - embedder->SubmitFrame(gr_context.get(), std::move(surface_frame)); + embedder->SubmitFrame(gr_context.get(), std::move(surface_frame), nullptr); EXPECT_CALL(*jni_mock, FlutterViewEndFrame()); embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 3fc52d9dd5f5b..feb58fbec9f73 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -462,9 +462,22 @@ ); } -bool FlutterPlatformViewsController::SubmitFrame(GrDirectContext* gr_context, - std::shared_ptr ios_context, - std::unique_ptr frame) { +bool FlutterPlatformViewsController::SubmitFrame( + GrDirectContext* gr_context, + std::shared_ptr ios_context, + std::unique_ptr frame, + const std::shared_ptr& gpu_disable_sync_switch) { + bool result = false; + gpu_disable_sync_switch->Execute( + fml::SyncSwitch::Handlers().SetIfTrue([&] { result = false; }).SetIfFalse([&] { + result = SubmitFrameGpuSafe(gr_context, ios_context, std::move(frame)); + })); + return result; +} + +bool FlutterPlatformViewsController::SubmitFrameGpuSafe(GrDirectContext* gr_context, + std::shared_ptr ios_context, + std::unique_ptr frame) { // Any UIKit related code has to run on main thread. FML_DCHECK([[NSThread currentThread] isMainThread]); if (flutter_view_ == nullptr) { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm index 0334720337049..31a19b29b6e9c 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm @@ -800,8 +800,10 @@ - (void)testFlutterPlatformViewControllerSubmitFrameWithoutFlutterViewNotCrashin auto mock_surface = std::make_unique( nullptr, true, [](const flutter::SurfaceFrame& surface_frame, SkCanvas* canvas) { return false; }); - XCTAssertFalse( - flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface))); + auto is_gpu_disabled = std::make_shared(); + is_gpu_disabled->SetSwitch(false); + XCTAssertFalse(flutterPlatformViewsController->SubmitFrame( + nullptr, nullptr, std::move(mock_surface), is_gpu_disabled)); auto embeddedViewParams_2 = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); @@ -810,8 +812,10 @@ - (void)testFlutterPlatformViewControllerSubmitFrameWithoutFlutterViewNotCrashin auto mock_surface_submit_false = std::make_unique( nullptr, true, [](const flutter::SurfaceFrame& surface_frame, SkCanvas* canvas) { return true; }); - XCTAssertTrue(flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, - std::move(mock_surface_submit_false))); + auto gpu_is_disabled = std::make_shared(); + gpu_is_disabled->SetSwitch(false); + XCTAssertTrue(flutterPlatformViewsController->SubmitFrame( + nullptr, nullptr, std::move(mock_surface_submit_false), gpu_is_disabled)); flutterPlatformViewsController->Reset(); } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index 36f69c7822e4c..41925624c450d 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -172,7 +172,8 @@ class FlutterPlatformViewsController { bool SubmitFrame(GrDirectContext* gr_context, std::shared_ptr ios_context, - std::unique_ptr frame); + std::unique_ptr frame, + const std::shared_ptr& gpu_disable_sync_switch); // Invoked at the very end of a frame. // After invoking this method, nothing should happen on the current TaskRunner during the same @@ -304,6 +305,10 @@ class FlutterPlatformViewsController { // Commit a CATransaction if |BeginCATransaction| has been called during the frame. void CommitCATransactionIfNeeded(); + bool SubmitFrameGpuSafe(GrDirectContext* gr_context, + std::shared_ptr ios_context, + std::unique_ptr frame); + FML_DISALLOW_COPY_AND_ASSIGN(FlutterPlatformViewsController); }; diff --git a/shell/platform/darwin/ios/ios_external_view_embedder.h b/shell/platform/darwin/ios/ios_external_view_embedder.h index 6c023d1b793e1..84d30416d27f0 100644 --- a/shell/platform/darwin/ios/ios_external_view_embedder.h +++ b/shell/platform/darwin/ios/ios_external_view_embedder.h @@ -53,8 +53,10 @@ class IOSExternalViewEmbedder : public ExternalViewEmbedder { SkCanvas* CompositeEmbeddedView(int view_id) override; // |ExternalViewEmbedder| - void SubmitFrame(GrDirectContext* context, - std::unique_ptr frame) override; + void SubmitFrame( + GrDirectContext* context, + std::unique_ptr frame, + const std::shared_ptr& gpu_disable_sync_switch) override; // |ExternalViewEmbedder| void EndFrame( diff --git a/shell/platform/darwin/ios/ios_external_view_embedder.mm b/shell/platform/darwin/ios/ios_external_view_embedder.mm index 46cb3014b636f..cfb34248dba38 100644 --- a/shell/platform/darwin/ios/ios_external_view_embedder.mm +++ b/shell/platform/darwin/ios/ios_external_view_embedder.mm @@ -72,11 +72,14 @@ } // |ExternalViewEmbedder| -void IOSExternalViewEmbedder::SubmitFrame(GrDirectContext* context, - std::unique_ptr frame) { +void IOSExternalViewEmbedder::SubmitFrame( + GrDirectContext* context, + std::unique_ptr frame, + const std::shared_ptr& gpu_disable_sync_switch) { TRACE_EVENT0("flutter", "IOSExternalViewEmbedder::SubmitFrame"); FML_CHECK(platform_views_controller_); - platform_views_controller_->SubmitFrame(std::move(context), ios_context_, std::move(frame)); + platform_views_controller_->SubmitFrame(std::move(context), ios_context_, std::move(frame), + gpu_disable_sync_switch); TRACE_EVENT0("flutter", "IOSExternalViewEmbedder::DidSubmitFrame"); } diff --git a/shell/platform/embedder/embedder_external_view_embedder.cc b/shell/platform/embedder/embedder_external_view_embedder.cc index b69907a8ddbe5..fc6c2905331c9 100644 --- a/shell/platform/embedder/embedder_external_view_embedder.cc +++ b/shell/platform/embedder/embedder_external_view_embedder.cc @@ -133,7 +133,8 @@ static FlutterBackingStoreConfig MakeBackingStoreConfig( // |ExternalViewEmbedder| void EmbedderExternalViewEmbedder::SubmitFrame( GrDirectContext* context, - std::unique_ptr frame) { + std::unique_ptr frame, + const std::shared_ptr& gpu_disable_sync_switch) { auto [matched_render_targets, pending_keys] = render_target_cache_.GetExistingTargetsInCache(pending_views_); diff --git a/shell/platform/embedder/embedder_external_view_embedder.h b/shell/platform/embedder/embedder_external_view_embedder.h index ffc6411b8ad5b..e668e6eb1d1f7 100644 --- a/shell/platform/embedder/embedder_external_view_embedder.h +++ b/shell/platform/embedder/embedder_external_view_embedder.h @@ -91,8 +91,10 @@ class EmbedderExternalViewEmbedder final : public ExternalViewEmbedder { SkCanvas* CompositeEmbeddedView(int view_id) override; // |ExternalViewEmbedder| - void SubmitFrame(GrDirectContext* context, - std::unique_ptr frame) override; + void SubmitFrame( + GrDirectContext* context, + std::unique_ptr frame, + const std::shared_ptr& gpu_disable_sync_switch) override; // |ExternalViewEmbedder| SkCanvas* GetRootCanvas() override; diff --git a/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.cc b/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.cc index 987db137595e8..4faf062b197c0 100644 --- a/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.cc +++ b/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.cc @@ -141,7 +141,8 @@ void FuchsiaExternalViewEmbedder::EndFrame( void FuchsiaExternalViewEmbedder::SubmitFrame( GrDirectContext* context, - std::unique_ptr frame) { + std::unique_ptr frame, + const std::shared_ptr& gpu_disable_sync_switch) { TRACE_EVENT0("flutter", "FuchsiaExternalViewEmbedder::SubmitFrame"); std::vector> frame_surfaces; std::unordered_map frame_surface_indices; diff --git a/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.h b/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.h index c2aa386e220e3..d20225cb6dee2 100644 --- a/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.h +++ b/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.h @@ -74,8 +74,10 @@ class FuchsiaExternalViewEmbedder final : public flutter::ExternalViewEmbedder { fml::RefPtr raster_thread_merger) override; // |ExternalViewEmbedder| - void SubmitFrame(GrDirectContext* context, - std::unique_ptr frame) override; + void SubmitFrame( + GrDirectContext* context, + std::unique_ptr frame, + const std::shared_ptr& gpu_disable_sync_switch) override; // |ExternalViewEmbedder| void CancelFrame() override { Reset(); } diff --git a/shell/platform/fuchsia/flutter/platform_view_unittest.cc b/shell/platform/fuchsia/flutter/platform_view_unittest.cc index eb3a16b32f097..559d2b8f7cbfb 100644 --- a/shell/platform/fuchsia/flutter/platform_view_unittest.cc +++ b/shell/platform/fuchsia/flutter/platform_view_unittest.cc @@ -45,7 +45,9 @@ class MockExternalViewEmbedder : public flutter::ExternalViewEmbedder { double device_pixel_ratio, fml::RefPtr raster_thread_merger) override {} void SubmitFrame(GrDirectContext* context, - std::unique_ptr frame) override { + std::unique_ptr frame, + const std::shared_ptr& + gpu_disable_sync_switch) override { return; }