started providing the GPU sync switch to external view embedders (#22302) (#22760)

Co-authored-by: gaaclarke <30870216+gaaclarke@users.noreply.github.com>
diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc
index 9441c8d..273006c 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<SurfaceFrame> frame) {
+void ExternalViewEmbedder::SubmitFrame(
+    GrDirectContext* context,
+    std::unique_ptr<SurfaceFrame> frame,
+    const std::shared_ptr<fml::SyncSwitch>& gpu_disable_sync_switch) {
   frame->Submit();
 };
 
diff --git a/flow/embedded_views.h b/flow/embedded_views.h
index e82d9e8..4d6853a 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 @@
   // 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<SurfaceFrame> frame);
+  virtual void SubmitFrame(
+      GrDirectContext* context,
+      std::unique_ptr<SurfaceFrame> frame,
+      const std::shared_ptr<fml::SyncSwitch>& 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 1d326a7..3733e95 100644
--- a/shell/common/rasterizer.cc
+++ b/shell/common/rasterizer.cc
@@ -469,8 +469,9 @@
     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 38611b0..357a0f3 100644
--- a/shell/common/rasterizer_unittests.cc
+++ b/shell/common/rasterizer_unittests.cc
@@ -55,9 +55,11 @@
                    fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger));
   MOCK_METHOD0(GetCurrentCanvases, std::vector<SkCanvas*>());
   MOCK_METHOD1(CompositeEmbeddedView, SkCanvas*(int view_id));
-  MOCK_METHOD2(SubmitFrame,
-               void(GrDirectContext* context,
-                    std::unique_ptr<SurfaceFrame> frame));
+  MOCK_METHOD3(
+      SubmitFrame,
+      void(GrDirectContext* context,
+           std::unique_ptr<SurfaceFrame> frame,
+           const std::shared_ptr<fml::SyncSwitch>& gpu_disable_sync_switch));
   MOCK_METHOD2(EndFrame,
                void(bool should_resubmit_frame,
                     fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger));
diff --git a/shell/common/shell_test_external_view_embedder.cc b/shell/common/shell_test_external_view_embedder.cc
index 5a8edc1..80e8210 100644
--- a/shell/common/shell_test_external_view_embedder.cc
+++ b/shell/common/shell_test_external_view_embedder.cc
@@ -63,7 +63,8 @@
 // |ExternalViewEmbedder|
 void ShellTestExternalViewEmbedder::SubmitFrame(
     GrDirectContext* context,
-    std::unique_ptr<SurfaceFrame> frame) {
+    std::unique_ptr<SurfaceFrame> frame,
+    const std::shared_ptr<fml::SyncSwitch>& 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 72c101e..1782a03 100644
--- a/shell/common/shell_test_external_view_embedder.h
+++ b/shell/common/shell_test_external_view_embedder.h
@@ -62,8 +62,10 @@
   SkCanvas* CompositeEmbeddedView(int view_id) override;
 
   // |ExternalViewEmbedder|
-  void SubmitFrame(GrDirectContext* context,
-                   std::unique_ptr<SurfaceFrame> frame) override;
+  void SubmitFrame(
+      GrDirectContext* context,
+      std::unique_ptr<SurfaceFrame> frame,
+      const std::shared_ptr<fml::SyncSwitch>& 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 9e544d6..69370e7 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 @@
 // |ExternalViewEmbedder|
 void AndroidExternalViewEmbedder::SubmitFrame(
     GrDirectContext* context,
-    std::unique_ptr<SurfaceFrame> frame) {
+    std::unique_ptr<SurfaceFrame> frame,
+    const std::shared_ptr<fml::SyncSwitch>& 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 7398ce4..71d7e7c 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 @@
   std::vector<SkCanvas*> GetCurrentCanvases() override;
 
   // |ExternalViewEmbedder|
-  void SubmitFrame(GrDirectContext* context,
-                   std::unique_ptr<SurfaceFrame> frame) override;
+  void SubmitFrame(
+      GrDirectContext* context,
+      std::unique_ptr<SurfaceFrame> frame,
+      const std::shared_ptr<fml::SyncSwitch>& 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 1c161cc..3ea187c 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 @@
           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 @@
           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 @@
           }
           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 @@
         std::make_unique<SurfaceFrame>(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 @@
         std::make_unique<SurfaceFrame>(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 3fc52d9..feb58fb 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<IOSContext> ios_context,
-                                                 std::unique_ptr<SurfaceFrame> frame) {
+bool FlutterPlatformViewsController::SubmitFrame(
+    GrDirectContext* gr_context,
+    std::shared_ptr<IOSContext> ios_context,
+    std::unique_ptr<SurfaceFrame> frame,
+    const std::shared_ptr<fml::SyncSwitch>& 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<IOSContext> ios_context,
+                                                        std::unique_ptr<SurfaceFrame> 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 0334720..31a19b2 100644
--- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm
+++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm
@@ -800,8 +800,10 @@
   auto mock_surface = std::make_unique<flutter::SurfaceFrame>(
       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<fml::SyncSwitch>();
+  is_gpu_disabled->SetSwitch(false);
+  XCTAssertFalse(flutterPlatformViewsController->SubmitFrame(
+      nullptr, nullptr, std::move(mock_surface), is_gpu_disabled));
 
   auto embeddedViewParams_2 =
       std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack);
@@ -810,8 +812,10 @@
   auto mock_surface_submit_false = std::make_unique<flutter::SurfaceFrame>(
       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<fml::SyncSwitch>();
+  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 36f69c7..4192562 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 @@
 
   bool SubmitFrame(GrDirectContext* gr_context,
                    std::shared_ptr<IOSContext> ios_context,
-                   std::unique_ptr<SurfaceFrame> frame);
+                   std::unique_ptr<SurfaceFrame> frame,
+                   const std::shared_ptr<fml::SyncSwitch>& 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 @@
   // Commit a CATransaction if |BeginCATransaction| has been called during the frame.
   void CommitCATransactionIfNeeded();
 
+  bool SubmitFrameGpuSafe(GrDirectContext* gr_context,
+                          std::shared_ptr<IOSContext> ios_context,
+                          std::unique_ptr<SurfaceFrame> 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 6c023d1..84d3041 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 @@
   SkCanvas* CompositeEmbeddedView(int view_id) override;
 
   // |ExternalViewEmbedder|
-  void SubmitFrame(GrDirectContext* context,
-                   std::unique_ptr<SurfaceFrame> frame) override;
+  void SubmitFrame(
+      GrDirectContext* context,
+      std::unique_ptr<SurfaceFrame> frame,
+      const std::shared_ptr<fml::SyncSwitch>& 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 46cb301..cfb3424 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<SurfaceFrame> frame) {
+void IOSExternalViewEmbedder::SubmitFrame(
+    GrDirectContext* context,
+    std::unique_ptr<SurfaceFrame> frame,
+    const std::shared_ptr<fml::SyncSwitch>& 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 b69907a..fc6c290 100644
--- a/shell/platform/embedder/embedder_external_view_embedder.cc
+++ b/shell/platform/embedder/embedder_external_view_embedder.cc
@@ -133,7 +133,8 @@
 // |ExternalViewEmbedder|
 void EmbedderExternalViewEmbedder::SubmitFrame(
     GrDirectContext* context,
-    std::unique_ptr<SurfaceFrame> frame) {
+    std::unique_ptr<SurfaceFrame> frame,
+    const std::shared_ptr<fml::SyncSwitch>& 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 ffc6411..e668e6e 100644
--- a/shell/platform/embedder/embedder_external_view_embedder.h
+++ b/shell/platform/embedder/embedder_external_view_embedder.h
@@ -91,8 +91,10 @@
   SkCanvas* CompositeEmbeddedView(int view_id) override;
 
   // |ExternalViewEmbedder|
-  void SubmitFrame(GrDirectContext* context,
-                   std::unique_ptr<SurfaceFrame> frame) override;
+  void SubmitFrame(
+      GrDirectContext* context,
+      std::unique_ptr<SurfaceFrame> frame,
+      const std::shared_ptr<fml::SyncSwitch>& 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 987db13..4faf062 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::SubmitFrame(
     GrDirectContext* context,
-    std::unique_ptr<flutter::SurfaceFrame> frame) {
+    std::unique_ptr<flutter::SurfaceFrame> frame,
+    const std::shared_ptr<fml::SyncSwitch>& gpu_disable_sync_switch) {
   TRACE_EVENT0("flutter", "FuchsiaExternalViewEmbedder::SubmitFrame");
   std::vector<std::unique_ptr<SurfaceProducerSurface>> frame_surfaces;
   std::unordered_map<EmbedderLayerId, size_t> 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 c2aa386..d20225c 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 @@
       fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) override;
 
   // |ExternalViewEmbedder|
-  void SubmitFrame(GrDirectContext* context,
-                   std::unique_ptr<flutter::SurfaceFrame> frame) override;
+  void SubmitFrame(
+      GrDirectContext* context,
+      std::unique_ptr<flutter::SurfaceFrame> frame,
+      const std::shared_ptr<fml::SyncSwitch>& 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 eb3a16b..559d2b8 100644
--- a/shell/platform/fuchsia/flutter/platform_view_unittest.cc
+++ b/shell/platform/fuchsia/flutter/platform_view_unittest.cc
@@ -45,7 +45,9 @@
       double device_pixel_ratio,
       fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) override {}
   void SubmitFrame(GrDirectContext* context,
-                   std::unique_ptr<flutter::SurfaceFrame> frame) override {
+                   std::unique_ptr<flutter::SurfaceFrame> frame,
+                   const std::shared_ptr<fml::SyncSwitch>&
+                       gpu_disable_sync_switch) override {
     return;
   }