mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Made the Rasterizer avoid GPU calls when backgrounded (#18563)
This commit is contained in:
parent
a298f56429
commit
bef5ac6132
@ -58,7 +58,9 @@ TEST_F(ShellTest, VSyncTargetTime) {
|
||||
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());
|
||||
|
||||
|
||||
@ -28,26 +28,34 @@ static constexpr std::chrono::milliseconds kSkiaCleanupExpiration(15000);
|
||||
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 @@ void Rasterizer::Draw(fml::RefPtr<Pipeline<flutter::LayerTree>> pipeline) {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ sk_sp<SkImage> Rasterizer::DoMakeRasterSnapshot(
|
||||
|
||||
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) {
|
||||
|
||||
@ -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 @@ class Rasterizer final : public SnapshotDelegate {
|
||||
/// @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 @@ class Rasterizer final : public SnapshotDelegate {
|
||||
///
|
||||
/// @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 @@ class Rasterizer final : public SnapshotDelegate {
|
||||
/// @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 @@ class Rasterizer final : public SnapshotDelegate {
|
||||
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,
|
||||
|
||||
@ -58,7 +58,9 @@ static void StartupAndShutdownShell(benchmark::State& state,
|
||||
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());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -298,7 +298,8 @@ std::unique_ptr<Shell> ShellTest::CreateShell(
|
||||
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) {
|
||||
|
||||
@ -143,7 +143,8 @@ TEST_F(ShellTest,
|
||||
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());
|
||||
|
||||
@ -79,7 +79,8 @@ AndroidShellHolder::AndroidShellHolder(
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
@ -475,7 +475,8 @@ static constexpr int kNumProfilerSamplesPerSec = 5;
|
||||
|
||||
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()) {
|
||||
|
||||
@ -935,8 +935,8 @@ FlutterEngineResult FlutterEngineInitialize(size_t version,
|
||||
|
||||
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
|
||||
|
||||
@ -202,9 +202,9 @@ Engine::Engine(Delegate& delegate,
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@ -139,7 +139,8 @@ int RunTester(const flutter::Settings& settings,
|
||||
};
|
||||
|
||||
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, //
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user