Made the Rasterizer avoid GPU calls when backgrounded (#18563)
diff --git a/shell/common/animator_unittests.cc b/shell/common/animator_unittests.cc
index 34acb1d..0f5e432 100644
--- a/shell/common/animator_unittests.cc
+++ b/shell/common/animator_unittests.cc
@@ -58,7 +58,9 @@
ShellTestPlatformView::BackendType::kDefaultBackend, nullptr);
},
[](Shell& shell) {
- return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
+ return std::make_unique<Rasterizer>(
+ shell, shell.GetTaskRunners(),
+ shell.GetIsGpuDisabledSyncSwitch());
});
ASSERT_TRUE(DartVMRef::IsInstanceRunning());
diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc
index 522fdf8..30d50db 100644
--- a/shell/common/rasterizer.cc
+++ b/shell/common/rasterizer.cc
@@ -28,26 +28,34 @@
static Rasterizer::DummyDelegate dummy_delegate_;
Rasterizer::Rasterizer(
TaskRunners task_runners,
- std::unique_ptr<flutter::CompositorContext> compositor_context)
+ std::unique_ptr<flutter::CompositorContext> compositor_context,
+ std::shared_ptr<fml::SyncSwitch> is_gpu_disabled_sync_switch)
: Rasterizer(dummy_delegate_,
std::move(task_runners),
- std::move(compositor_context)) {}
-
-Rasterizer::Rasterizer(Delegate& delegate, TaskRunners task_runners)
- : Rasterizer(delegate,
- std::move(task_runners),
- std::make_unique<flutter::CompositorContext>(
- delegate.GetFrameBudget())) {}
+ std::move(compositor_context),
+ is_gpu_disabled_sync_switch) {}
Rasterizer::Rasterizer(
Delegate& delegate,
TaskRunners task_runners,
- std::unique_ptr<flutter::CompositorContext> compositor_context)
+ std::shared_ptr<fml::SyncSwitch> is_gpu_disabled_sync_switch)
+ : Rasterizer(delegate,
+ std::move(task_runners),
+ std::make_unique<flutter::CompositorContext>(
+ delegate.GetFrameBudget()),
+ is_gpu_disabled_sync_switch) {}
+
+Rasterizer::Rasterizer(
+ Delegate& delegate,
+ TaskRunners task_runners,
+ std::unique_ptr<flutter::CompositorContext> compositor_context,
+ std::shared_ptr<fml::SyncSwitch> is_gpu_disabled_sync_switch)
: delegate_(delegate),
task_runners_(std::move(task_runners)),
compositor_context_(std::move(compositor_context)),
user_override_resource_cache_bytes_(false),
- weak_factory_(this) {
+ weak_factory_(this),
+ is_gpu_disabled_sync_switch_(is_gpu_disabled_sync_switch) {
FML_DCHECK(compositor_context_);
}
@@ -168,31 +176,10 @@
}
}
-sk_sp<SkImage> Rasterizer::DoMakeRasterSnapshot(
- SkISize size,
- std::function<void(SkCanvas*)> draw_callback) {
- TRACE_EVENT0("flutter", __FUNCTION__);
-
- sk_sp<SkSurface> surface;
- SkImageInfo image_info = SkImageInfo::MakeN32Premul(
- size.width(), size.height(), SkColorSpace::MakeSRGB());
- if (surface_ == nullptr || surface_->GetContext() == nullptr) {
- // Raster surface is fine if there is no on screen surface. This might
- // happen in case of software rendering.
- surface = SkSurface::MakeRaster(image_info);
- } else {
- if (!surface_->MakeRenderContextCurrent()) {
- return nullptr;
- }
-
- // When there is an on screen surface, we need a render target SkSurface
- // because we want to access texture backed images.
- surface = SkSurface::MakeRenderTarget(surface_->GetContext(), // context
- SkBudgeted::kNo, // budgeted
- image_info // image info
- );
- }
-
+namespace {
+sk_sp<SkImage> DrawSnapshot(
+ sk_sp<SkSurface> surface,
+ const std::function<void(SkCanvas*)>& draw_callback) {
if (surface == nullptr || surface->getCanvas() == nullptr) {
return nullptr;
}
@@ -219,6 +206,45 @@
return nullptr;
}
+} // namespace
+
+sk_sp<SkImage> Rasterizer::DoMakeRasterSnapshot(
+ SkISize size,
+ std::function<void(SkCanvas*)> draw_callback) {
+ TRACE_EVENT0("flutter", __FUNCTION__);
+ sk_sp<SkImage> result;
+ SkImageInfo image_info = SkImageInfo::MakeN32Premul(
+ size.width(), size.height(), SkColorSpace::MakeSRGB());
+ if (surface_ == nullptr || surface_->GetContext() == nullptr) {
+ // Raster surface is fine if there is no on screen surface. This might
+ // happen in case of software rendering.
+ sk_sp<SkSurface> surface = SkSurface::MakeRaster(image_info);
+ result = DrawSnapshot(surface, draw_callback);
+ } else {
+ is_gpu_disabled_sync_switch_->Execute(
+ fml::SyncSwitch::Handlers()
+ .SetIfTrue([&] {
+ sk_sp<SkSurface> surface = SkSurface::MakeRaster(image_info);
+ result = DrawSnapshot(surface, draw_callback);
+ })
+ .SetIfFalse([&] {
+ if (!surface_->MakeRenderContextCurrent()) {
+ return;
+ }
+
+ // When there is an on screen surface, we need a render target
+ // SkSurface because we want to access texture backed images.
+ sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(
+ surface_->GetContext(), // context
+ SkBudgeted::kNo, // budgeted
+ image_info // image info
+ );
+ result = DrawSnapshot(surface, draw_callback);
+ }));
+ }
+
+ return result;
+}
sk_sp<SkImage> Rasterizer::MakeRasterSnapshot(sk_sp<SkPicture> picture,
SkISize picture_size) {
diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h
index a254d84..39111b0 100644
--- a/shell/common/rasterizer.h
+++ b/shell/common/rasterizer.h
@@ -15,6 +15,7 @@
#include "flutter/fml/closure.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/fml/raster_thread_merger.h"
+#include "flutter/fml/synchronization/sync_switch.h"
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/fml/time/time_delta.h"
#include "flutter/fml/time/time_point.h"
@@ -101,9 +102,13 @@
/// @param[in] task_runners The task runners used by the shell.
/// @param[in] compositor_context The compositor context used to hold all
/// the GPU state used by the rasterizer.
+ /// @param[in] is_gpu_disabled_sync_switch
+ /// A `SyncSwitch` for handling disabling of the GPU (typically happens
+ /// when an app is backgrounded)
///
Rasterizer(TaskRunners task_runners,
- std::unique_ptr<flutter::CompositorContext> compositor_context);
+ std::unique_ptr<flutter::CompositorContext> compositor_context,
+ std::shared_ptr<fml::SyncSwitch> is_gpu_disabled_sync_switch);
//----------------------------------------------------------------------------
/// @brief Creates a new instance of a rasterizer. Rasterizers may only
@@ -116,8 +121,13 @@
///
/// @param[in] delegate The rasterizer delegate.
/// @param[in] task_runners The task runners used by the shell.
+ /// @param[in] is_gpu_disabled_sync_switch
+ /// A `SyncSwitch` for handling disabling of the GPU (typically happens
+ /// when an app is backgrounded)
///
- Rasterizer(Delegate& delegate, TaskRunners task_runners);
+ Rasterizer(Delegate& delegate,
+ TaskRunners task_runners,
+ std::shared_ptr<fml::SyncSwitch> is_gpu_disabled_sync_switch);
//----------------------------------------------------------------------------
/// @brief Creates a new instance of a rasterizer. Rasterizers may only
@@ -132,10 +142,14 @@
/// @param[in] task_runners The task runners used by the shell.
/// @param[in] compositor_context The compositor context used to hold all
/// the GPU state used by the rasterizer.
+ /// @param[in] is_gpu_disabled_sync_switch
+ /// A `SyncSwitch` for handling disabling of the GPU (typically happens
+ /// when an app is backgrounded)
///
Rasterizer(Delegate& delegate,
TaskRunners task_runners,
- std::unique_ptr<flutter::CompositorContext> compositor_context);
+ std::unique_ptr<flutter::CompositorContext> compositor_context,
+ std::shared_ptr<fml::SyncSwitch> is_gpu_disabled_sync_switch);
//----------------------------------------------------------------------------
/// @brief Destroys the rasterizer. This must happen on the GPU task
@@ -432,6 +446,7 @@
std::optional<size_t> max_cache_bytes_;
fml::TaskRunnerAffineWeakPtrFactory<Rasterizer> weak_factory_;
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger_;
+ std::shared_ptr<fml::SyncSwitch> is_gpu_disabled_sync_switch_;
// |SnapshotDelegate|
sk_sp<SkImage> MakeRasterSnapshot(sk_sp<SkPicture> picture,
diff --git a/shell/common/shell_benchmarks.cc b/shell/common/shell_benchmarks.cc
index c5b2751..9d3a1a3 100644
--- a/shell/common/shell_benchmarks.cc
+++ b/shell/common/shell_benchmarks.cc
@@ -58,7 +58,9 @@
return std::make_unique<PlatformView>(shell, shell.GetTaskRunners());
},
[](Shell& shell) {
- return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
+ return std::make_unique<Rasterizer>(
+ shell, shell.GetTaskRunners(),
+ shell.GetIsGpuDisabledSyncSwitch());
});
}
diff --git a/shell/common/shell_test.cc b/shell/common/shell_test.cc
index 8ef045c..8bd7d8b 100644
--- a/shell/common/shell_test.cc
+++ b/shell/common/shell_test.cc
@@ -298,7 +298,8 @@
shell_test_external_view_embedder);
},
[](Shell& shell) {
- return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
+ return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners(),
+ shell.GetIsGpuDisabledSyncSwitch());
});
}
void ShellTest::DestroyShell(std::unique_ptr<Shell> shell) {
diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc
index 589d593..5318458 100644
--- a/shell/common/shell_unittests.cc
+++ b/shell/common/shell_unittests.cc
@@ -143,7 +143,8 @@
ShellTestPlatformView::BackendType::kDefaultBackend, nullptr);
},
[](Shell& shell) {
- return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
+ return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners(),
+ shell.GetIsGpuDisabledSyncSwitch());
});
ASSERT_TRUE(ValidateShell(shell.get()));
ASSERT_TRUE(DartVMRef::IsInstanceRunning());
diff --git a/shell/platform/android/android_shell_holder.cc b/shell/platform/android/android_shell_holder.cc
index fe4d85a..bde98f8 100644
--- a/shell/platform/android/android_shell_holder.cc
+++ b/shell/platform/android/android_shell_holder.cc
@@ -79,7 +79,8 @@
};
Shell::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) {
- return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
+ return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners(),
+ shell.GetIsGpuDisabledSyncSwitch());
};
// The current thread will be used as the platform thread. Ensure that the
diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm
index 59eae77..0b671b0 100644
--- a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm
+++ b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm
@@ -475,7 +475,8 @@
flutter::Shell::CreateCallback<flutter::Rasterizer> on_create_rasterizer =
[](flutter::Shell& shell) {
- return std::make_unique<flutter::Rasterizer>(shell, shell.GetTaskRunners());
+ return std::make_unique<flutter::Rasterizer>(shell, shell.GetTaskRunners(),
+ shell.GetIsGpuDisabledSyncSwitch());
};
if (flutter::IsIosEmbeddedViewsPreviewEnabled()) {
diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc
index bfbcb00..9091b33 100644
--- a/shell/platform/embedder/embedder.cc
+++ b/shell/platform/embedder/embedder.cc
@@ -935,8 +935,8 @@
flutter::Shell::CreateCallback<flutter::Rasterizer> on_create_rasterizer =
[](flutter::Shell& shell) {
- return std::make_unique<flutter::Rasterizer>(shell,
- shell.GetTaskRunners());
+ return std::make_unique<flutter::Rasterizer>(
+ shell, shell.GetTaskRunners(), shell.GetIsGpuDisabledSyncSwitch());
};
// TODO(chinmaygarde): This is the wrong spot for this. It belongs in the
diff --git a/shell/platform/fuchsia/flutter/engine.cc b/shell/platform/fuchsia/flutter/engine.cc
index 0f6fa1e..fc2c2fe 100644
--- a/shell/platform/fuchsia/flutter/engine.cc
+++ b/shell/platform/fuchsia/flutter/engine.cc
@@ -202,9 +202,9 @@
}
return std::make_unique<flutter::Rasterizer>(
- shell.GetTaskRunners(), // task runners
- std::move(compositor_context) // compositor context
- );
+ /*task_runners=*/shell.GetTaskRunners(),
+ /*compositor_context=*/std::move(compositor_context),
+ /*is_gpu_disabled_sync_switch=*/shell.GetIsGpuDisabledSyncSwitch());
});
UpdateNativeThreadLabelNames(thread_label_, task_runners);
diff --git a/shell/testing/tester_main.cc b/shell/testing/tester_main.cc
index cab6481..73b6ce7 100644
--- a/shell/testing/tester_main.cc
+++ b/shell/testing/tester_main.cc
@@ -139,7 +139,8 @@
};
Shell::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) {
- return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
+ return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners(),
+ shell.GetIsGpuDisabledSyncSwitch());
};
auto shell = Shell::Create(task_runners, //