forked from firka/flutter
[Impeller] Avoid encoding metal commands while the GPU is unavailable when decoding images. (flutter/engine#42349)
Fixes https://github.com/flutter/flutter/issues/126878 This disables device private upload on iOS when backgrounded, and disables mipmap generation when backgrounded. We don't have a good way to test the core problem in this repo because it only reproduces on physical iOS hardware - simulators don't really care if you do this stuff in the background. I'll write a devicelab test in the framework to capture this. In the mean time it can be reviewed. We could consider making the IOManager a shared_ptr instead of having an fml::WeakPtr and that'd clean up some of the extra arguments to engine construction - or we could consider vending the sync switch from impeller::Context unconditionally, but it's pretty iOS specific...
This commit is contained in:
@@ -385,10 +385,13 @@ static bool Bind(PassBindingsCache& pass,
|
||||
}
|
||||
|
||||
if (texture.NeedsMipmapGeneration()) {
|
||||
// TODO(127697): generate mips when the GPU is available on iOS.
|
||||
#if !FML_OS_IOS
|
||||
VALIDATION_LOG
|
||||
<< "Texture at binding index " << bind_index
|
||||
<< " has a mip count > 1, but the mipmap has not been generated.";
|
||||
return false;
|
||||
#endif // !FML_OS_IOS
|
||||
}
|
||||
|
||||
return pass.SetTexture(stage, bind_index,
|
||||
|
||||
@@ -16,14 +16,16 @@ std::unique_ptr<ImageDecoder> ImageDecoder::Make(
|
||||
const Settings& settings,
|
||||
const TaskRunners& runners,
|
||||
std::shared_ptr<fml::ConcurrentTaskRunner> concurrent_task_runner,
|
||||
fml::WeakPtr<IOManager> io_manager) {
|
||||
fml::WeakPtr<IOManager> io_manager,
|
||||
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch) {
|
||||
#if IMPELLER_SUPPORTS_RENDERING
|
||||
if (settings.enable_impeller) {
|
||||
return std::make_unique<ImageDecoderImpeller>(
|
||||
runners, //
|
||||
std::move(concurrent_task_runner), //
|
||||
std::move(io_manager), //
|
||||
settings.enable_wide_gamut);
|
||||
settings.enable_wide_gamut, //
|
||||
gpu_disabled_switch);
|
||||
}
|
||||
#endif // IMPELLER_SUPPORTS_RENDERING
|
||||
return std::make_unique<ImageDecoderSkia>(
|
||||
|
||||
@@ -27,7 +27,8 @@ class ImageDecoder {
|
||||
const Settings& settings,
|
||||
const TaskRunners& runners,
|
||||
std::shared_ptr<fml::ConcurrentTaskRunner> concurrent_task_runner,
|
||||
fml::WeakPtr<IOManager> io_manager);
|
||||
fml::WeakPtr<IOManager> io_manager,
|
||||
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch);
|
||||
|
||||
virtual ~ImageDecoder();
|
||||
|
||||
|
||||
@@ -80,9 +80,11 @@ ImageDecoderImpeller::ImageDecoderImpeller(
|
||||
const TaskRunners& runners,
|
||||
std::shared_ptr<fml::ConcurrentTaskRunner> concurrent_task_runner,
|
||||
const fml::WeakPtr<IOManager>& io_manager,
|
||||
bool supports_wide_gamut)
|
||||
bool supports_wide_gamut,
|
||||
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch)
|
||||
: ImageDecoder(runners, std::move(concurrent_task_runner), io_manager),
|
||||
supports_wide_gamut_(supports_wide_gamut) {
|
||||
supports_wide_gamut_(supports_wide_gamut),
|
||||
gpu_disabled_switch_(gpu_disabled_switch) {
|
||||
std::promise<std::shared_ptr<impeller::Context>> context_promise;
|
||||
context_ = context_promise.get_future();
|
||||
runners_.GetIOTaskRunner()->PostTask(fml::MakeCopyable(
|
||||
@@ -246,18 +248,11 @@ DecompressResult ImageDecoderImpeller::DecompressTexture(
|
||||
.image_info = scaled_bitmap->info()};
|
||||
}
|
||||
|
||||
std::pair<sk_sp<DlImage>, std::string>
|
||||
ImageDecoderImpeller::UploadTextureToPrivate(
|
||||
/// Only call this method if the GPU is available.
|
||||
static std::pair<sk_sp<DlImage>, std::string> UnsafeUploadTextureToPrivate(
|
||||
const std::shared_ptr<impeller::Context>& context,
|
||||
const std::shared_ptr<impeller::DeviceBuffer>& buffer,
|
||||
const SkImageInfo& image_info) {
|
||||
TRACE_EVENT0("impeller", __FUNCTION__);
|
||||
if (!context) {
|
||||
return std::make_pair(nullptr, "No Impeller context is available");
|
||||
}
|
||||
if (!buffer) {
|
||||
return std::make_pair(nullptr, "No Impeller device buffer is available");
|
||||
}
|
||||
const auto pixel_format =
|
||||
impeller::skia_conversions::ToPixelFormat(image_info.colorType());
|
||||
if (!pixel_format) {
|
||||
@@ -318,10 +313,40 @@ ImageDecoderImpeller::UploadTextureToPrivate(
|
||||
impeller::DlImageImpeller::Make(std::move(dest_texture)), std::string());
|
||||
}
|
||||
|
||||
std::pair<sk_sp<DlImage>, std::string>
|
||||
ImageDecoderImpeller::UploadTextureToPrivate(
|
||||
const std::shared_ptr<impeller::Context>& context,
|
||||
const std::shared_ptr<impeller::DeviceBuffer>& buffer,
|
||||
const SkImageInfo& image_info,
|
||||
std::shared_ptr<SkBitmap> bitmap,
|
||||
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch) {
|
||||
TRACE_EVENT0("impeller", __FUNCTION__);
|
||||
if (!context) {
|
||||
return std::make_pair(nullptr, "No Impeller context is available");
|
||||
}
|
||||
if (!buffer) {
|
||||
return std::make_pair(nullptr, "No Impeller device buffer is available");
|
||||
}
|
||||
|
||||
std::pair<sk_sp<DlImage>, std::string> result;
|
||||
gpu_disabled_switch->Execute(
|
||||
fml::SyncSwitch::Handlers()
|
||||
.SetIfFalse([&result, context, buffer, image_info] {
|
||||
result = UnsafeUploadTextureToPrivate(context, buffer, image_info);
|
||||
})
|
||||
.SetIfTrue([&result, context, bitmap, gpu_disabled_switch] {
|
||||
// create_mips is false because we already know the GPU is disabled.
|
||||
result = UploadTextureToShared(context, bitmap, gpu_disabled_switch,
|
||||
/*create_mips=*/false);
|
||||
}));
|
||||
return result;
|
||||
}
|
||||
|
||||
std::pair<sk_sp<DlImage>, std::string>
|
||||
ImageDecoderImpeller::UploadTextureToShared(
|
||||
const std::shared_ptr<impeller::Context>& context,
|
||||
std::shared_ptr<SkBitmap> bitmap,
|
||||
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch,
|
||||
bool create_mips) {
|
||||
TRACE_EVENT0("impeller", __FUNCTION__);
|
||||
if (!context) {
|
||||
@@ -370,32 +395,40 @@ ImageDecoderImpeller::UploadTextureToShared(
|
||||
texture->SetLabel(impeller::SPrintF("ui.Image(%p)", texture.get()).c_str());
|
||||
|
||||
if (texture_descriptor.mip_count > 1u && create_mips) {
|
||||
auto command_buffer = context->CreateCommandBuffer();
|
||||
if (!command_buffer) {
|
||||
std::string decode_error(
|
||||
"Could not create command buffer for mipmap generation.");
|
||||
FML_DLOG(ERROR) << decode_error;
|
||||
return std::make_pair(nullptr, decode_error);
|
||||
}
|
||||
command_buffer->SetLabel("Mipmap Command Buffer");
|
||||
std::optional<std::string> decode_error;
|
||||
|
||||
auto blit_pass = command_buffer->CreateBlitPass();
|
||||
if (!blit_pass) {
|
||||
std::string decode_error(
|
||||
"Could not create blit pass for mipmap generation.");
|
||||
FML_DLOG(ERROR) << decode_error;
|
||||
return std::make_pair(nullptr, decode_error);
|
||||
}
|
||||
blit_pass->SetLabel("Mipmap Blit Pass");
|
||||
blit_pass->GenerateMipmap(texture);
|
||||
// The only platform that needs mipmapping unconditionally is GL.
|
||||
// GL based platforms never disable GPU access.
|
||||
// This is only really needed for iOS.
|
||||
gpu_disabled_switch->Execute(fml::SyncSwitch::Handlers().SetIfFalse(
|
||||
[context, &texture, &decode_error] {
|
||||
auto command_buffer = context->CreateCommandBuffer();
|
||||
if (!command_buffer) {
|
||||
decode_error =
|
||||
"Could not create command buffer for mipmap generation.";
|
||||
return;
|
||||
}
|
||||
command_buffer->SetLabel("Mipmap Command Buffer");
|
||||
|
||||
blit_pass->EncodeCommands(context->GetResourceAllocator());
|
||||
if (!command_buffer->SubmitCommands()) {
|
||||
std::string decode_error("Failed to submit blit pass command buffer.");
|
||||
FML_DLOG(ERROR) << decode_error;
|
||||
return std::make_pair(nullptr, decode_error);
|
||||
auto blit_pass = command_buffer->CreateBlitPass();
|
||||
if (!blit_pass) {
|
||||
decode_error = "Could not create blit pass for mipmap generation.";
|
||||
return;
|
||||
}
|
||||
blit_pass->SetLabel("Mipmap Blit Pass");
|
||||
blit_pass->GenerateMipmap(texture);
|
||||
|
||||
blit_pass->EncodeCommands(context->GetResourceAllocator());
|
||||
if (!command_buffer->SubmitCommands()) {
|
||||
decode_error = "Failed to submit blit pass command buffer.";
|
||||
return;
|
||||
}
|
||||
command_buffer->WaitUntilScheduled();
|
||||
}));
|
||||
if (decode_error.has_value()) {
|
||||
FML_DLOG(ERROR) << decode_error.value();
|
||||
return std::make_pair(nullptr, decode_error.value());
|
||||
}
|
||||
command_buffer->WaitUntilScheduled();
|
||||
}
|
||||
|
||||
return std::make_pair(impeller::DlImageImpeller::Make(std::move(texture)),
|
||||
@@ -429,8 +462,8 @@ void ImageDecoderImpeller::Decode(fml::RefPtr<ImageDescriptor> descriptor,
|
||||
target_size = SkISize::Make(target_width, target_height), //
|
||||
io_runner = runners_.GetIOTaskRunner(), //
|
||||
result,
|
||||
supports_wide_gamut = supports_wide_gamut_ //
|
||||
]() {
|
||||
supports_wide_gamut = supports_wide_gamut_, //
|
||||
gpu_disabled_switch = gpu_disabled_switch_]() {
|
||||
if (!context) {
|
||||
result(nullptr, "No Impeller context is available");
|
||||
return;
|
||||
@@ -446,24 +479,28 @@ void ImageDecoderImpeller::Decode(fml::RefPtr<ImageDescriptor> descriptor,
|
||||
result(nullptr, bitmap_result.decode_error);
|
||||
return;
|
||||
}
|
||||
auto upload_texture_and_invoke_result = [result, context,
|
||||
bitmap_result]() {
|
||||
// TODO(jonahwilliams): remove ifdef once blit from buffer to
|
||||
// texture is implemented on other platforms.
|
||||
auto upload_texture_and_invoke_result = [result, context, bitmap_result,
|
||||
gpu_disabled_switch]() {
|
||||
// TODO(jonahwilliams): remove ifdef once blit from buffer
|
||||
// to texture is implemented on other platforms.
|
||||
sk_sp<DlImage> image;
|
||||
std::string decode_error;
|
||||
|
||||
#ifdef FML_OS_IOS
|
||||
std::tie(image, decode_error) = UploadTextureToPrivate(
|
||||
context, bitmap_result.device_buffer, bitmap_result.image_info);
|
||||
context, bitmap_result.device_buffer, bitmap_result.image_info,
|
||||
bitmap_result.sk_bitmap, gpu_disabled_switch);
|
||||
#else
|
||||
std::tie(image, decode_error) =
|
||||
UploadTextureToShared(context, bitmap_result.sk_bitmap);
|
||||
#endif
|
||||
UploadTextureToShared(context, bitmap_result.sk_bitmap,
|
||||
gpu_disabled_switch, /*create_mips=*/true);
|
||||
#endif // FML_OS_IOS
|
||||
result(image, decode_error);
|
||||
};
|
||||
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/123058
|
||||
// Technically we don't need to post tasks to the io runner, but without
|
||||
// this forced serialization we can end up overloading the GPU and/or
|
||||
// TODO(jonahwilliams):
|
||||
// https://github.com/flutter/flutter/issues/123058 Technically we
|
||||
// don't need to post tasks to the io runner, but without this
|
||||
// forced serialization we can end up overloading the GPU and/or
|
||||
// competing with raster workloads.
|
||||
io_runner->PostTask(upload_texture_and_invoke_result);
|
||||
});
|
||||
|
||||
@@ -50,7 +50,8 @@ class ImageDecoderImpeller final : public ImageDecoder {
|
||||
const TaskRunners& runners,
|
||||
std::shared_ptr<fml::ConcurrentTaskRunner> concurrent_task_runner,
|
||||
const fml::WeakPtr<IOManager>& io_manager,
|
||||
bool supports_wide_gamut);
|
||||
bool supports_wide_gamut,
|
||||
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch);
|
||||
|
||||
~ImageDecoderImpeller() override;
|
||||
|
||||
@@ -72,27 +73,35 @@ class ImageDecoderImpeller final : public ImageDecoder {
|
||||
/// @param context The Impeller graphics context.
|
||||
/// @param buffer A host buffer containing the image to be uploaded.
|
||||
/// @param image_info Format information about the particular image.
|
||||
/// @param bitmap A bitmap containg the image to be uploaded.
|
||||
/// @param gpu_disabled_switch Whether the GPU is available command encoding.
|
||||
/// @return A DlImage.
|
||||
static std::pair<sk_sp<DlImage>, std::string> UploadTextureToPrivate(
|
||||
const std::shared_ptr<impeller::Context>& context,
|
||||
const std::shared_ptr<impeller::DeviceBuffer>& buffer,
|
||||
const SkImageInfo& image_info);
|
||||
const SkImageInfo& image_info,
|
||||
std::shared_ptr<SkBitmap> bitmap,
|
||||
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch);
|
||||
|
||||
/// @brief Create a host visible texture from the provided bitmap.
|
||||
/// @param context The Impeller graphics context.
|
||||
/// @param bitmap A bitmap containg the image to be uploaded.
|
||||
/// @param create_mips Whether mipmaps should be generated for the given
|
||||
/// image.
|
||||
/// @param gpu_disabled_switch Whether the GPU is available for mipmap
|
||||
/// creation.
|
||||
/// @return A DlImage.
|
||||
static std::pair<sk_sp<DlImage>, std::string> UploadTextureToShared(
|
||||
const std::shared_ptr<impeller::Context>& context,
|
||||
std::shared_ptr<SkBitmap> bitmap,
|
||||
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch,
|
||||
bool create_mips = true);
|
||||
|
||||
private:
|
||||
using FutureContext = std::shared_future<std::shared_ptr<impeller::Context>>;
|
||||
FutureContext context_;
|
||||
const bool supports_wide_gamut_;
|
||||
std::shared_ptr<fml::SyncSwitch> gpu_disabled_switch_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(ImageDecoderImpeller);
|
||||
};
|
||||
|
||||
@@ -138,9 +138,12 @@ class TestImpellerContext : public impeller::Context {
|
||||
}
|
||||
|
||||
std::shared_ptr<CommandBuffer> CreateCommandBuffer() const override {
|
||||
command_buffer_count_ += 1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mutable size_t command_buffer_count_ = 0;
|
||||
|
||||
private:
|
||||
std::shared_ptr<const Capabilities> capabilities_;
|
||||
};
|
||||
@@ -280,7 +283,8 @@ TEST_F(ImageDecoderFixtureTest, CanCreateImageDecoder) {
|
||||
TestIOManager manager(runners.GetIOTaskRunner());
|
||||
Settings settings;
|
||||
auto decoder = ImageDecoder::Make(settings, runners, loop->GetTaskRunner(),
|
||||
manager.GetWeakIOManager());
|
||||
manager.GetWeakIOManager(),
|
||||
std::make_shared<fml::SyncSwitch>());
|
||||
ASSERT_NE(decoder, nullptr);
|
||||
});
|
||||
}
|
||||
@@ -331,7 +335,8 @@ TEST_F(ImageDecoderFixtureTest, InvalidImageResultsError) {
|
||||
TestIOManager manager(runners.GetIOTaskRunner());
|
||||
Settings settings;
|
||||
auto decoder = ImageDecoder::Make(settings, runners, loop->GetTaskRunner(),
|
||||
manager.GetWeakIOManager());
|
||||
manager.GetWeakIOManager(),
|
||||
std::make_shared<fml::SyncSwitch>());
|
||||
|
||||
auto data = OpenFixtureAsSkData("ThisDoesNotExist.jpg");
|
||||
ASSERT_FALSE(data);
|
||||
@@ -370,9 +375,9 @@ TEST_F(ImageDecoderFixtureTest, ValidImageResultsInSuccess) {
|
||||
};
|
||||
auto decode_image = [&]() {
|
||||
Settings settings;
|
||||
std::unique_ptr<ImageDecoder> image_decoder =
|
||||
ImageDecoder::Make(settings, runners, loop->GetTaskRunner(),
|
||||
io_manager->GetWeakIOManager());
|
||||
std::unique_ptr<ImageDecoder> image_decoder = ImageDecoder::Make(
|
||||
settings, runners, loop->GetTaskRunner(),
|
||||
io_manager->GetWeakIOManager(), std::make_shared<fml::SyncSwitch>());
|
||||
|
||||
auto data = OpenFixtureAsSkData("DashInNooglerHat.jpg");
|
||||
|
||||
@@ -426,6 +431,34 @@ float HalfToFloat(uint16_t half) {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST_F(ImageDecoderFixtureTest, ImpellerUploadToSharedNoGpu) {
|
||||
#if !IMPELLER_SUPPORTS_RENDERING
|
||||
GTEST_SKIP() << "Impeller only test.";
|
||||
#endif // IMPELLER_SUPPORTS_RENDERING
|
||||
|
||||
auto no_gpu_access_context =
|
||||
std::make_shared<impeller::TestImpellerContext>();
|
||||
auto gpu_disabled_switch = std::make_shared<fml::SyncSwitch>(true);
|
||||
|
||||
auto info = SkImageInfo::Make(10, 10, SkColorType::kRGBA_8888_SkColorType,
|
||||
SkAlphaType::kPremul_SkAlphaType);
|
||||
auto bitmap = std::make_shared<SkBitmap>();
|
||||
bitmap->allocPixels(info, 10 * 4);
|
||||
impeller::DeviceBufferDescriptor desc;
|
||||
desc.size = bitmap->computeByteSize();
|
||||
auto buffer = std::make_shared<impeller::TestImpellerDeviceBuffer>(desc);
|
||||
|
||||
auto result = ImageDecoderImpeller::UploadTextureToPrivate(
|
||||
no_gpu_access_context, buffer, info, bitmap, gpu_disabled_switch);
|
||||
ASSERT_EQ(no_gpu_access_context->command_buffer_count_, 0ul);
|
||||
ASSERT_EQ(result.second, "");
|
||||
|
||||
result = ImageDecoderImpeller::UploadTextureToShared(
|
||||
no_gpu_access_context, bitmap, gpu_disabled_switch, true);
|
||||
ASSERT_EQ(no_gpu_access_context->command_buffer_count_, 0ul);
|
||||
ASSERT_EQ(result.second, "");
|
||||
}
|
||||
|
||||
TEST_F(ImageDecoderFixtureTest, ImpellerNullColorspace) {
|
||||
auto info = SkImageInfo::Make(10, 10, SkColorType::kRGBA_8888_SkColorType,
|
||||
SkAlphaType::kPremul_SkAlphaType);
|
||||
@@ -642,9 +675,9 @@ TEST_F(ImageDecoderFixtureTest, ExifDataIsRespectedOnDecode) {
|
||||
SkISize decoded_size = SkISize::MakeEmpty();
|
||||
auto decode_image = [&]() {
|
||||
Settings settings;
|
||||
std::unique_ptr<ImageDecoder> image_decoder =
|
||||
ImageDecoder::Make(settings, runners, loop->GetTaskRunner(),
|
||||
io_manager->GetWeakIOManager());
|
||||
std::unique_ptr<ImageDecoder> image_decoder = ImageDecoder::Make(
|
||||
settings, runners, loop->GetTaskRunner(),
|
||||
io_manager->GetWeakIOManager(), std::make_shared<fml::SyncSwitch>());
|
||||
|
||||
auto data = OpenFixtureAsSkData("Horizontal.jpg");
|
||||
|
||||
@@ -703,9 +736,9 @@ TEST_F(ImageDecoderFixtureTest, CanDecodeWithoutAGPUContext) {
|
||||
|
||||
auto decode_image = [&]() {
|
||||
Settings settings;
|
||||
std::unique_ptr<ImageDecoder> image_decoder =
|
||||
ImageDecoder::Make(settings, runners, loop->GetTaskRunner(),
|
||||
io_manager->GetWeakIOManager());
|
||||
std::unique_ptr<ImageDecoder> image_decoder = ImageDecoder::Make(
|
||||
settings, runners, loop->GetTaskRunner(),
|
||||
io_manager->GetWeakIOManager(), std::make_shared<fml::SyncSwitch>());
|
||||
|
||||
auto data = OpenFixtureAsSkData("DashInNooglerHat.jpg");
|
||||
|
||||
@@ -771,7 +804,8 @@ TEST_F(ImageDecoderFixtureTest, CanDecodeWithResizes) {
|
||||
PostTaskSync(runners.GetUITaskRunner(), [&]() {
|
||||
Settings settings;
|
||||
image_decoder = ImageDecoder::Make(settings, runners, loop->GetTaskRunner(),
|
||||
io_manager->GetWeakIOManager());
|
||||
io_manager->GetWeakIOManager(),
|
||||
std::make_shared<fml::SyncSwitch>());
|
||||
});
|
||||
|
||||
// Setup a generic decoding utility that gives us the final decoded size.
|
||||
|
||||
@@ -159,6 +159,7 @@ MultiFrameCodec::State::GetNextFrameImage(
|
||||
// without mipmap creation there is no command buffer encoding done.
|
||||
return ImageDecoderImpeller::UploadTextureToShared(
|
||||
impeller_context, std::make_shared<SkBitmap>(bitmap),
|
||||
std::make_shared<fml::SyncSwitch>(),
|
||||
/*create_mips=*/false);
|
||||
}
|
||||
#endif // IMPELLER_SUPPORTS_RENDERING
|
||||
|
||||
@@ -45,7 +45,8 @@ Engine::Engine(
|
||||
std::unique_ptr<Animator> animator,
|
||||
fml::WeakPtr<IOManager> io_manager,
|
||||
const std::shared_ptr<FontCollection>& font_collection,
|
||||
std::unique_ptr<RuntimeController> runtime_controller)
|
||||
std::unique_ptr<RuntimeController> runtime_controller,
|
||||
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch)
|
||||
: delegate_(delegate),
|
||||
settings_(settings),
|
||||
animator_(std::move(animator)),
|
||||
@@ -54,7 +55,8 @@ Engine::Engine(
|
||||
image_decoder_(ImageDecoder::Make(settings_,
|
||||
task_runners,
|
||||
std::move(image_decoder_task_runner),
|
||||
std::move(io_manager))),
|
||||
std::move(io_manager),
|
||||
gpu_disabled_switch)),
|
||||
task_runners_(task_runners),
|
||||
weak_factory_(this) {
|
||||
pointer_data_dispatcher_ = dispatcher_maker(*this);
|
||||
@@ -71,7 +73,8 @@ Engine::Engine(Delegate& delegate,
|
||||
fml::WeakPtr<IOManager> io_manager,
|
||||
fml::RefPtr<SkiaUnrefQueue> unref_queue,
|
||||
fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
|
||||
std::shared_ptr<VolatilePathTracker> volatile_path_tracker)
|
||||
std::shared_ptr<VolatilePathTracker> volatile_path_tracker,
|
||||
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch)
|
||||
: Engine(delegate,
|
||||
dispatcher_maker,
|
||||
vm.GetConcurrentWorkerTaskRunner(),
|
||||
@@ -80,7 +83,8 @@ Engine::Engine(Delegate& delegate,
|
||||
std::move(animator),
|
||||
io_manager,
|
||||
std::make_shared<FontCollection>(),
|
||||
nullptr) {
|
||||
nullptr,
|
||||
gpu_disabled_switch) {
|
||||
runtime_controller_ = std::make_unique<RuntimeController>(
|
||||
*this, // runtime delegate
|
||||
&vm, // VM
|
||||
@@ -112,7 +116,8 @@ std::unique_ptr<Engine> Engine::Spawn(
|
||||
std::unique_ptr<Animator> animator,
|
||||
const std::string& initial_route,
|
||||
const fml::WeakPtr<IOManager>& io_manager,
|
||||
fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate) const {
|
||||
fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
|
||||
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch) const {
|
||||
auto result = std::make_unique<Engine>(
|
||||
/*delegate=*/delegate,
|
||||
/*dispatcher_maker=*/dispatcher_maker,
|
||||
@@ -123,7 +128,8 @@ std::unique_ptr<Engine> Engine::Spawn(
|
||||
/*animator=*/std::move(animator),
|
||||
/*io_manager=*/io_manager,
|
||||
/*font_collection=*/font_collection_,
|
||||
/*runtime_controller=*/nullptr);
|
||||
/*runtime_controller=*/nullptr,
|
||||
/*gpu_disabled_switch=*/gpu_disabled_switch);
|
||||
result->runtime_controller_ = runtime_controller_->Spawn(
|
||||
/*p_client=*/*result,
|
||||
/*advisory_script_uri=*/settings.advisory_script_uri,
|
||||
|
||||
@@ -309,7 +309,8 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
|
||||
std::unique_ptr<Animator> animator,
|
||||
fml::WeakPtr<IOManager> io_manager,
|
||||
const std::shared_ptr<FontCollection>& font_collection,
|
||||
std::unique_ptr<RuntimeController> runtime_controller);
|
||||
std::unique_ptr<RuntimeController> runtime_controller,
|
||||
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Creates an instance of the engine. This is done by the Shell
|
||||
@@ -364,7 +365,8 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
|
||||
fml::WeakPtr<IOManager> io_manager,
|
||||
fml::RefPtr<SkiaUnrefQueue> unref_queue,
|
||||
fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
|
||||
std::shared_ptr<VolatilePathTracker> volatile_path_tracker);
|
||||
std::shared_ptr<VolatilePathTracker> volatile_path_tracker,
|
||||
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Create a Engine that shares as many resources as
|
||||
@@ -382,7 +384,8 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
|
||||
std::unique_ptr<Animator> animator,
|
||||
const std::string& initial_route,
|
||||
const fml::WeakPtr<IOManager>& io_manager,
|
||||
fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate) const;
|
||||
fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
|
||||
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch) const;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Destroys the engine engine. Called by the shell on the UI task
|
||||
|
||||
@@ -162,7 +162,8 @@ TEST_F(EngineTest, Create) {
|
||||
/*animator=*/std::move(animator_),
|
||||
/*io_manager=*/io_manager_,
|
||||
/*font_collection=*/std::make_shared<FontCollection>(),
|
||||
/*runtime_controller=*/std::move(runtime_controller_));
|
||||
/*runtime_controller=*/std::move(runtime_controller_),
|
||||
/*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
|
||||
EXPECT_TRUE(engine);
|
||||
});
|
||||
}
|
||||
@@ -183,7 +184,8 @@ TEST_F(EngineTest, DispatchPlatformMessageUnknown) {
|
||||
/*animator=*/std::move(animator_),
|
||||
/*io_manager=*/io_manager_,
|
||||
/*font_collection=*/std::make_shared<FontCollection>(),
|
||||
/*runtime_controller=*/std::move(mock_runtime_controller));
|
||||
/*runtime_controller=*/std::move(mock_runtime_controller),
|
||||
/*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
|
||||
|
||||
fml::RefPtr<PlatformMessageResponse> response =
|
||||
fml::MakeRefCounted<MockResponse>();
|
||||
@@ -209,7 +211,8 @@ TEST_F(EngineTest, DispatchPlatformMessageInitialRoute) {
|
||||
/*animator=*/std::move(animator_),
|
||||
/*io_manager=*/io_manager_,
|
||||
/*font_collection=*/std::make_shared<FontCollection>(),
|
||||
/*runtime_controller=*/std::move(mock_runtime_controller));
|
||||
/*runtime_controller=*/std::move(mock_runtime_controller),
|
||||
/*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
|
||||
|
||||
fml::RefPtr<PlatformMessageResponse> response =
|
||||
fml::MakeRefCounted<MockResponse>();
|
||||
@@ -242,7 +245,8 @@ TEST_F(EngineTest, DispatchPlatformMessageInitialRouteIgnored) {
|
||||
/*animator=*/std::move(animator_),
|
||||
/*io_manager=*/io_manager_,
|
||||
/*font_collection=*/std::make_shared<FontCollection>(),
|
||||
/*runtime_controller=*/std::move(mock_runtime_controller));
|
||||
/*runtime_controller=*/std::move(mock_runtime_controller),
|
||||
/*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
|
||||
|
||||
fml::RefPtr<PlatformMessageResponse> response =
|
||||
fml::MakeRefCounted<MockResponse>();
|
||||
@@ -274,10 +278,12 @@ TEST_F(EngineTest, SpawnSharesFontLibrary) {
|
||||
/*animator=*/std::move(animator_),
|
||||
/*io_manager=*/io_manager_,
|
||||
/*font_collection=*/std::make_shared<FontCollection>(),
|
||||
/*runtime_controller=*/std::move(mock_runtime_controller));
|
||||
/*runtime_controller=*/std::move(mock_runtime_controller),
|
||||
/*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
|
||||
|
||||
auto spawn = engine->Spawn(delegate_, dispatcher_maker_, settings_, nullptr,
|
||||
std::string(), io_manager_, snapshot_delegate_);
|
||||
auto spawn =
|
||||
engine->Spawn(delegate_, dispatcher_maker_, settings_, nullptr,
|
||||
std::string(), io_manager_, snapshot_delegate_, nullptr);
|
||||
EXPECT_TRUE(spawn != nullptr);
|
||||
EXPECT_EQ(&engine->GetFontCollection(), &spawn->GetFontCollection());
|
||||
});
|
||||
@@ -300,10 +306,12 @@ TEST_F(EngineTest, SpawnWithCustomInitialRoute) {
|
||||
/*animator=*/std::move(animator_),
|
||||
/*io_manager=*/io_manager_,
|
||||
/*font_collection=*/std::make_shared<FontCollection>(),
|
||||
/*runtime_controller=*/std::move(mock_runtime_controller));
|
||||
/*runtime_controller=*/std::move(mock_runtime_controller),
|
||||
/*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
|
||||
|
||||
auto spawn = engine->Spawn(delegate_, dispatcher_maker_, settings_, nullptr,
|
||||
"/foo", io_manager_, snapshot_delegate_);
|
||||
auto spawn =
|
||||
engine->Spawn(delegate_, dispatcher_maker_, settings_, nullptr, "/foo",
|
||||
io_manager_, snapshot_delegate_, nullptr);
|
||||
EXPECT_TRUE(spawn != nullptr);
|
||||
ASSERT_EQ("/foo", spawn->InitialRoute());
|
||||
});
|
||||
@@ -332,14 +340,16 @@ TEST_F(EngineTest, SpawnResetsViewportMetrics) {
|
||||
/*animator=*/std::move(animator_),
|
||||
/*io_manager=*/io_manager_,
|
||||
/*font_collection=*/std::make_shared<FontCollection>(),
|
||||
/*runtime_controller=*/std::move(mock_runtime_controller));
|
||||
/*runtime_controller=*/std::move(mock_runtime_controller),
|
||||
/*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
|
||||
|
||||
auto& old_platform_data = engine->GetRuntimeController()->GetPlatformData();
|
||||
EXPECT_EQ(old_platform_data.viewport_metrics.physical_width, kViewWidth);
|
||||
EXPECT_EQ(old_platform_data.viewport_metrics.physical_height, kViewHeight);
|
||||
|
||||
auto spawn = engine->Spawn(delegate_, dispatcher_maker_, settings_, nullptr,
|
||||
std::string(), io_manager_, snapshot_delegate_);
|
||||
auto spawn =
|
||||
engine->Spawn(delegate_, dispatcher_maker_, settings_, nullptr,
|
||||
std::string(), io_manager_, snapshot_delegate_, nullptr);
|
||||
EXPECT_TRUE(spawn != nullptr);
|
||||
auto& new_viewport_metrics =
|
||||
spawn->GetRuntimeController()->GetPlatformData().viewport_metrics;
|
||||
@@ -365,14 +375,15 @@ TEST_F(EngineTest, SpawnWithCustomSettings) {
|
||||
/*animator=*/std::move(animator_),
|
||||
/*io_manager=*/io_manager_,
|
||||
/*font_collection=*/std::make_shared<FontCollection>(),
|
||||
/*runtime_controller=*/std::move(mock_runtime_controller));
|
||||
/*runtime_controller=*/std::move(mock_runtime_controller),
|
||||
/*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
|
||||
|
||||
Settings custom_settings = settings_;
|
||||
custom_settings.persistent_isolate_data =
|
||||
std::make_shared<fml::DataMapping>("foo");
|
||||
auto spawn =
|
||||
engine->Spawn(delegate_, dispatcher_maker_, custom_settings, nullptr,
|
||||
std::string(), io_manager_, snapshot_delegate_);
|
||||
std::string(), io_manager_, snapshot_delegate_, nullptr);
|
||||
EXPECT_TRUE(spawn != nullptr);
|
||||
auto new_persistent_isolate_data =
|
||||
const_cast<RuntimeController*>(spawn->GetRuntimeController())
|
||||
@@ -405,7 +416,8 @@ TEST_F(EngineTest, PassesLoadDartDeferredLibraryErrorToRuntime) {
|
||||
/*animator=*/std::move(animator_),
|
||||
/*io_manager=*/io_manager_,
|
||||
/*font_collection=*/std::make_shared<FontCollection>(),
|
||||
/*runtime_controller=*/std::move(mock_runtime_controller));
|
||||
/*runtime_controller=*/std::move(mock_runtime_controller),
|
||||
/*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
|
||||
|
||||
engine->LoadDartDeferredLibraryError(error_id, error_message, true);
|
||||
});
|
||||
|
||||
@@ -54,19 +54,21 @@ std::unique_ptr<Engine> CreateEngine(
|
||||
const fml::WeakPtr<IOManager>& io_manager,
|
||||
const fml::RefPtr<SkiaUnrefQueue>& unref_queue,
|
||||
const fml::TaskRunnerAffineWeakPtr<SnapshotDelegate>& snapshot_delegate,
|
||||
const std::shared_ptr<VolatilePathTracker>& volatile_path_tracker) {
|
||||
return std::make_unique<Engine>(delegate, //
|
||||
dispatcher_maker, //
|
||||
vm, //
|
||||
isolate_snapshot, //
|
||||
task_runners, //
|
||||
platform_data, //
|
||||
settings, //
|
||||
std::move(animator), //
|
||||
io_manager, //
|
||||
unref_queue, //
|
||||
snapshot_delegate, //
|
||||
volatile_path_tracker);
|
||||
const std::shared_ptr<VolatilePathTracker>& volatile_path_tracker,
|
||||
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch) {
|
||||
return std::make_unique<Engine>(delegate, //
|
||||
dispatcher_maker, //
|
||||
vm, //
|
||||
isolate_snapshot, //
|
||||
task_runners, //
|
||||
platform_data, //
|
||||
settings, //
|
||||
std::move(animator), //
|
||||
io_manager, //
|
||||
unref_queue, //
|
||||
snapshot_delegate, //
|
||||
volatile_path_tracker, //
|
||||
gpu_disabled_switch);
|
||||
}
|
||||
|
||||
// Though there can be multiple shells, some settings apply to all components in
|
||||
@@ -301,7 +303,8 @@ std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
|
||||
weak_io_manager_future.get(), //
|
||||
unref_queue_future.get(), //
|
||||
snapshot_delegate_future.get(), //
|
||||
shell->volatile_path_tracker_));
|
||||
shell->volatile_path_tracker_,
|
||||
shell->is_gpu_disabled_sync_switch_));
|
||||
}));
|
||||
|
||||
if (!shell->Setup(std::move(platform_view), //
|
||||
@@ -538,7 +541,8 @@ std::unique_ptr<Shell> Shell::Spawn(
|
||||
const fml::WeakPtr<IOManager>& io_manager,
|
||||
const fml::RefPtr<SkiaUnrefQueue>& unref_queue,
|
||||
fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
|
||||
const std::shared_ptr<VolatilePathTracker>& volatile_path_tracker) {
|
||||
const std::shared_ptr<VolatilePathTracker>& volatile_path_tracker,
|
||||
const std::shared_ptr<fml::SyncSwitch>& is_gpu_disabled_sync_switch) {
|
||||
return engine->Spawn(
|
||||
/*delegate=*/delegate,
|
||||
/*dispatcher_maker=*/dispatcher_maker,
|
||||
@@ -546,7 +550,8 @@ std::unique_ptr<Shell> Shell::Spawn(
|
||||
/*animator=*/std::move(animator),
|
||||
/*initial_route=*/initial_route,
|
||||
/*io_manager=*/io_manager,
|
||||
/*snapshot_delegate=*/std::move(snapshot_delegate));
|
||||
/*snapshot_delegate=*/std::move(snapshot_delegate),
|
||||
/*gpu_disabled_switch=*/is_gpu_disabled_sync_switch);
|
||||
},
|
||||
is_gpu_disabled);
|
||||
result->RunEngine(std::move(run_configuration));
|
||||
|
||||
@@ -126,7 +126,8 @@ class Shell final : public PlatformView::Delegate,
|
||||
fml::WeakPtr<IOManager> io_manager,
|
||||
fml::RefPtr<SkiaUnrefQueue> unref_queue,
|
||||
fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
|
||||
std::shared_ptr<VolatilePathTracker> volatile_path_tracker)>
|
||||
std::shared_ptr<VolatilePathTracker> volatile_path_tracker,
|
||||
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch)>
|
||||
EngineCreateCallback;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -356,6 +357,7 @@ class Shell final : public PlatformView::Delegate,
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Accessor for the disable GPU SyncSwitch.
|
||||
// |Rasterizer::Delegate|
|
||||
std::shared_ptr<const fml::SyncSwitch> GetIsGpuDisabledSyncSwitch()
|
||||
const override;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user