diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 7762d8304ab6d..8c214363396a8 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -401,7 +401,6 @@ FILE: ../../../flutter/lib/ui/semantics/semantics_update.cc FILE: ../../../flutter/lib/ui/semantics/semantics_update.h FILE: ../../../flutter/lib/ui/semantics/semantics_update_builder.cc FILE: ../../../flutter/lib/ui/semantics/semantics_update_builder.h -FILE: ../../../flutter/lib/ui/snapshot_delegate.h FILE: ../../../flutter/lib/ui/text.dart FILE: ../../../flutter/lib/ui/text/asset_manager_font_provider.cc FILE: ../../../flutter/lib/ui/text/asset_manager_font_provider.h diff --git a/lib/ui/BUILD.gn b/lib/ui/BUILD.gn index d1b4dc7e0ad4c..a1f15b09676e3 100644 --- a/lib/ui/BUILD.gn +++ b/lib/ui/BUILD.gn @@ -76,7 +76,6 @@ source_set("ui") { "semantics/semantics_update.h", "semantics/semantics_update_builder.cc", "semantics/semantics_update_builder.h", - "snapshot_delegate.h", "text/asset_manager_font_provider.cc", "text/asset_manager_font_provider.h", "text/font_collection.cc", diff --git a/lib/ui/painting/picture.cc b/lib/ui/painting/picture.cc index 98c37edc115f7..1b70ffed65ba6 100644 --- a/lib/ui/painting/picture.cc +++ b/lib/ui/painting/picture.cc @@ -5,9 +5,11 @@ #include "flutter/lib/ui/painting/picture.h" #include "flutter/fml/make_copyable.h" +#include "flutter/fml/trace_event.h" #include "flutter/lib/ui/painting/canvas.h" #include "flutter/lib/ui/ui_dart_state.h" #include "third_party/skia/include/core/SkImage.h" +#include "third_party/skia/include/core/SkSurface.h" #include "third_party/tonic/converter/dart_converter.h" #include "third_party/tonic/dart_args.h" #include "third_party/tonic/dart_binding_macros.h" @@ -16,6 +18,64 @@ #include "third_party/tonic/logging/dart_invoke.h" namespace flutter { +namespace { + +sk_sp MakeSnapshotSurface(const SkISize& picture_size, + fml::WeakPtr resource_context) { + SkImageInfo image_info = SkImageInfo::MakeN32Premul( + picture_size.width(), picture_size.height(), SkColorSpace::MakeSRGB()); + if (resource_context) { + return SkSurface::MakeRenderTarget(resource_context.get(), // context + SkBudgeted::kNo, // budgeted + image_info // image info + ); + } else { + return SkSurface::MakeRaster(image_info); + } +} + +/// Makes a RAM backed (Raster) image of a picture. +/// @param[in] picture The picture that will get converted to an image. +/// @param[in] surface The surface tha will be used to render the picture. This +/// will be CPU or GPU based. +/// @todo Currently this creates a RAM backed image regardless of what type of +/// surface is used. In certain instances we may want a GPU backed image +/// from a GPU surface to avoid the conversion. +sk_sp MakeRasterSnapshot(sk_sp picture, + sk_sp surface) { + TRACE_EVENT0("flutter", __FUNCTION__); + + if (surface == nullptr || surface->getCanvas() == nullptr) { + return nullptr; + } + + surface->getCanvas()->drawPicture(picture.get()); + + surface->getCanvas()->flush(); + + // Here device could mean GPU or CPU (depending on the supplied surface) and + // host means CPU; this is different from use cases like Flutter driver tests + // where device means mobile devices and host means laptops/desktops. + sk_sp device_snapshot; + { + TRACE_EVENT0("flutter", "MakeDeviceSnpashot"); + device_snapshot = surface->makeImageSnapshot(); + } + + if (device_snapshot == nullptr) { + return nullptr; + } + + { + TRACE_EVENT0("flutter", "DeviceHostTransfer"); + if (auto raster_image = device_snapshot->makeRasterImage()) { + return raster_image; + } + } + + return nullptr; +} +} // namespace IMPLEMENT_WRAPPERTYPEINFO(ui, Picture); @@ -75,8 +135,8 @@ Dart_Handle Picture::RasterizeToImage(sk_sp picture, new tonic::DartPersistentValue(dart_state, raw_image_callback); auto unref_queue = dart_state->GetSkiaUnrefQueue(); auto ui_task_runner = dart_state->GetTaskRunners().GetUITaskRunner(); - auto gpu_task_runner = dart_state->GetTaskRunners().GetGPUTaskRunner(); - auto snapshot_delegate = dart_state->GetSnapshotDelegate(); + auto io_task_runner = dart_state->GetTaskRunners().GetIOTaskRunner(); + fml::WeakPtr resource_context = dart_state->GetResourceContext(); // We can't create an image on this task runner because we don't have a // graphics context. Even if we did, it would be slow anyway. Also, this @@ -111,17 +171,16 @@ Dart_Handle Picture::RasterizeToImage(sk_sp picture, delete image_callback; }); - // Kick things off on the GPU. - fml::TaskRunner::RunNowOrPostTask( - gpu_task_runner, - [ui_task_runner, snapshot_delegate, picture, picture_bounds, ui_task] { - sk_sp raster_image = - snapshot_delegate->MakeRasterSnapshot(picture, picture_bounds); - - fml::TaskRunner::RunNowOrPostTask( - ui_task_runner, - [ui_task, raster_image]() { ui_task(raster_image); }); - }); + fml::TaskRunner::RunNowOrPostTask(io_task_runner, [ui_task_runner, picture, + picture_bounds, ui_task, + resource_context] { + sk_sp surface = + MakeSnapshotSurface(picture_bounds, resource_context); + sk_sp raster_image = MakeRasterSnapshot(picture, surface); + + fml::TaskRunner::RunNowOrPostTask( + ui_task_runner, [ui_task, raster_image]() { ui_task(raster_image); }); + }); return Dart_Null(); } diff --git a/lib/ui/snapshot_delegate.h b/lib/ui/snapshot_delegate.h deleted file mode 100644 index 9a771f1219cd8..0000000000000 --- a/lib/ui/snapshot_delegate.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef FLUTTER_LIB_UI_SNAPSHOT_DELEGATE_H_ -#define FLUTTER_LIB_UI_SNAPSHOT_DELEGATE_H_ - -#include "third_party/skia/include/core/SkImage.h" -#include "third_party/skia/include/core/SkPicture.h" - -namespace flutter { - -class SnapshotDelegate { - public: - virtual sk_sp MakeRasterSnapshot(sk_sp picture, - SkISize picture_size) = 0; -}; - -} // namespace flutter - -#endif // FLUTTER_LIB_UI_SNAPSHOT_DELEGATE_H_ diff --git a/lib/ui/ui_dart_state.cc b/lib/ui/ui_dart_state.cc index 8b84d18921957..41b12b6b21a47 100644 --- a/lib/ui/ui_dart_state.cc +++ b/lib/ui/ui_dart_state.cc @@ -17,7 +17,6 @@ UIDartState::UIDartState( TaskRunners task_runners, TaskObserverAdd add_callback, TaskObserverRemove remove_callback, - fml::WeakPtr snapshot_delegate, fml::WeakPtr io_manager, fml::WeakPtr image_decoder, std::string advisory_script_uri, @@ -28,7 +27,6 @@ UIDartState::UIDartState( : task_runners_(std::move(task_runners)), add_callback_(std::move(add_callback)), remove_callback_(std::move(remove_callback)), - snapshot_delegate_(std::move(snapshot_delegate)), io_manager_(std::move(io_manager)), image_decoder_(std::move(image_decoder)), advisory_script_uri_(std::move(advisory_script_uri)), @@ -115,10 +113,6 @@ void UIDartState::AddOrRemoveTaskObserver(bool add) { } } -fml::WeakPtr UIDartState::GetSnapshotDelegate() const { - return snapshot_delegate_; -} - fml::WeakPtr UIDartState::GetResourceContext() const { if (!io_manager_) { return {}; diff --git a/lib/ui/ui_dart_state.h b/lib/ui/ui_dart_state.h index 550c72ff98178..1654e75c9bea6 100644 --- a/lib/ui/ui_dart_state.h +++ b/lib/ui/ui_dart_state.h @@ -17,7 +17,6 @@ #include "flutter/lib/ui/io_manager.h" #include "flutter/lib/ui/isolate_name_server/isolate_name_server.h" #include "flutter/lib/ui/painting/image_decoder.h" -#include "flutter/lib/ui/snapshot_delegate.h" #include "third_party/dart/runtime/include/dart_api.h" #include "third_party/skia/include/gpu/GrContext.h" #include "third_party/tonic/dart_microtask_queue.h" @@ -50,8 +49,6 @@ class UIDartState : public tonic::DartState { fml::RefPtr GetSkiaUnrefQueue() const; - fml::WeakPtr GetSnapshotDelegate() const; - fml::WeakPtr GetResourceContext() const; fml::WeakPtr GetImageDecoder() const; @@ -78,7 +75,6 @@ class UIDartState : public tonic::DartState { UIDartState(TaskRunners task_runners, TaskObserverAdd add_callback, TaskObserverRemove remove_callback, - fml::WeakPtr snapshot_delegate, fml::WeakPtr io_manager, fml::WeakPtr image_decoder, std::string advisory_script_uri, @@ -101,7 +97,6 @@ class UIDartState : public tonic::DartState { const TaskRunners task_runners_; const TaskObserverAdd add_callback_; const TaskObserverRemove remove_callback_; - fml::WeakPtr snapshot_delegate_; fml::WeakPtr io_manager_; fml::WeakPtr image_decoder_; const std::string advisory_script_uri_; diff --git a/runtime/dart_isolate.cc b/runtime/dart_isolate.cc index b283aa5b6ba60..55ac852edacd3 100644 --- a/runtime/dart_isolate.cc +++ b/runtime/dart_isolate.cc @@ -35,7 +35,6 @@ std::weak_ptr DartIsolate::CreateRootIsolate( fml::RefPtr shared_snapshot, TaskRunners task_runners, std::unique_ptr window, - fml::WeakPtr snapshot_delegate, fml::WeakPtr io_manager, fml::WeakPtr image_decoder, std::string advisory_script_uri, @@ -57,18 +56,17 @@ std::weak_ptr DartIsolate::CreateRootIsolate( // being prepared to run. auto root_embedder_data = std::make_unique>( std::make_shared( - settings, // settings - std::move(isolate_snapshot), // isolate snapshot - std::move(shared_snapshot), // shared snapshot - task_runners, // task runners - std::move(snapshot_delegate), // snapshot delegate - std::move(io_manager), // IO manager - std::move(image_decoder), // Image Decoder - advisory_script_uri, // advisory URI - advisory_script_entrypoint, // advisory entrypoint - nullptr, // child isolate preparer - isolate_create_callback, // isolate create callback - isolate_shutdown_callback // isolate shutdown callback + settings, // settings + std::move(isolate_snapshot), // isolate snapshot + std::move(shared_snapshot), // shared snapshot + task_runners, // task runners + std::move(io_manager), // IO manager + std::move(image_decoder), // Image Decoder + advisory_script_uri, // advisory URI + advisory_script_entrypoint, // advisory entrypoint + nullptr, // child isolate preparer + isolate_create_callback, // isolate create callback + isolate_shutdown_callback // isolate shutdown callback )); std::tie(vm_isolate, embedder_isolate) = CreateDartVMAndEmbedderObjectPair( @@ -106,7 +104,6 @@ DartIsolate::DartIsolate(const Settings& settings, fml::RefPtr isolate_snapshot, fml::RefPtr shared_snapshot, TaskRunners task_runners, - fml::WeakPtr snapshot_delegate, fml::WeakPtr io_manager, fml::WeakPtr image_decoder, std::string advisory_script_uri, @@ -117,7 +114,6 @@ DartIsolate::DartIsolate(const Settings& settings, : UIDartState(std::move(task_runners), settings.task_observer_add, settings.task_observer_remove, - std::move(snapshot_delegate), std::move(io_manager), std::move(image_decoder), advisory_script_uri, @@ -599,7 +595,6 @@ Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate( vm_data->GetSharedSnapshot(), // shared snapshot null_task_runners, // task runners nullptr, // window - {}, // snapshot delegate {}, // IO Manager {}, // Image Decoder DART_VM_SERVICE_ISOLATE_NAME, // script uri @@ -712,7 +707,6 @@ DartIsolate::CreateDartVMAndEmbedderObjectPair( (*raw_embedder_isolate)->GetIsolateSnapshot(), // isolate_snapshot (*raw_embedder_isolate)->GetSharedSnapshot(), // shared_snapshot null_task_runners, // task_runners - fml::WeakPtr{}, // snapshot_delegate fml::WeakPtr{}, // io_manager fml::WeakPtr{}, // io_manager advisory_script_uri, // advisory_script_uri diff --git a/runtime/dart_isolate.h b/runtime/dart_isolate.h index 28732b120977b..5689367283a8d 100644 --- a/runtime/dart_isolate.h +++ b/runtime/dart_isolate.h @@ -14,7 +14,6 @@ #include "flutter/fml/macros.h" #include "flutter/fml/mapping.h" #include "flutter/lib/ui/io_manager.h" -#include "flutter/lib/ui/snapshot_delegate.h" #include "flutter/lib/ui/ui_dart_state.h" #include "flutter/lib/ui/window/window.h" #include "flutter/runtime/dart_snapshot.h" @@ -47,7 +46,6 @@ class DartIsolate : public UIDartState { fml::RefPtr shared_snapshot, TaskRunners task_runners, std::unique_ptr window, - fml::WeakPtr snapshot_delegate, fml::WeakPtr io_manager, fml::WeakPtr image_decoder, std::string advisory_script_uri, @@ -60,7 +58,6 @@ class DartIsolate : public UIDartState { fml::RefPtr isolate_snapshot, fml::RefPtr shared_snapshot, TaskRunners task_runners, - fml::WeakPtr snapshot_delegate, fml::WeakPtr io_manager, fml::WeakPtr image_decoder, std::string advisory_script_uri, diff --git a/runtime/dart_isolate_unittests.cc b/runtime/dart_isolate_unittests.cc index ae14042ecc743..2a693f86e714d 100644 --- a/runtime/dart_isolate_unittests.cc +++ b/runtime/dart_isolate_unittests.cc @@ -41,7 +41,6 @@ TEST_F(DartIsolateTest, RootIsolateCreationAndShutdown) { vm_data->GetSharedSnapshot(), // shared snapshot std::move(task_runners), // task runners nullptr, // window - {}, // snapshot delegate {}, // io manager {}, // image decoder "main.dart", // advisory uri @@ -75,7 +74,6 @@ TEST_F(DartIsolateTest, IsolateShutdownCallbackIsInIsolateScope) { vm_data->GetSharedSnapshot(), // shared snapshot std::move(task_runners), // task runners nullptr, // window - {}, // snapshot delegate {}, // io manager {}, // image decoder "main.dart", // advisory uri @@ -186,7 +184,6 @@ static void RunDartCodeInIsolate(DartVMRef& vm_ref, vm_data->GetSharedSnapshot(), // shared snapshot std::move(task_runners), // task runners nullptr, // window - {}, // snapshot delegate {}, // io manager {}, // image decoder "main.dart", // advisory uri diff --git a/runtime/dart_lifecycle_unittests.cc b/runtime/dart_lifecycle_unittests.cc index eec7aa6c9c4d5..a59cac8ca8c4d 100644 --- a/runtime/dart_lifecycle_unittests.cc +++ b/runtime/dart_lifecycle_unittests.cc @@ -56,7 +56,6 @@ static std::shared_ptr CreateAndRunRootIsolate( vm.GetSharedSnapshot(), // shared_snapshot runners, // task_runners {}, // window - {}, // snapshot_delegate {}, // io_manager {}, // image_decoder "main.dart", // advisory_script_uri diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc index e457f5986e1e7..7cc771ff8dd23 100644 --- a/runtime/runtime_controller.cc +++ b/runtime/runtime_controller.cc @@ -20,7 +20,6 @@ RuntimeController::RuntimeController( fml::RefPtr p_isolate_snapshot, fml::RefPtr p_shared_snapshot, TaskRunners p_task_runners, - fml::WeakPtr p_snapshot_delegate, fml::WeakPtr p_io_manager, fml::WeakPtr p_image_decoder, std::string p_advisory_script_uri, @@ -33,7 +32,6 @@ RuntimeController::RuntimeController( std::move(p_isolate_snapshot), std::move(p_shared_snapshot), std::move(p_task_runners), - std::move(p_snapshot_delegate), std::move(p_io_manager), std::move(p_image_decoder), std::move(p_advisory_script_uri), @@ -49,7 +47,6 @@ RuntimeController::RuntimeController( fml::RefPtr p_isolate_snapshot, fml::RefPtr p_shared_snapshot, TaskRunners p_task_runners, - fml::WeakPtr p_snapshot_delegate, fml::WeakPtr p_io_manager, fml::WeakPtr p_image_decoder, std::string p_advisory_script_uri, @@ -63,7 +60,6 @@ RuntimeController::RuntimeController( isolate_snapshot_(std::move(p_isolate_snapshot)), shared_snapshot_(std::move(p_shared_snapshot)), task_runners_(p_task_runners), - snapshot_delegate_(p_snapshot_delegate), io_manager_(p_io_manager), image_decoder_(p_image_decoder), advisory_script_uri_(p_advisory_script_uri), @@ -81,7 +77,6 @@ RuntimeController::RuntimeController( shared_snapshot_, // task_runners_, // std::make_unique(this), // - snapshot_delegate_, // io_manager_, // image_decoder_, // p_advisory_script_uri, // @@ -142,7 +137,6 @@ std::unique_ptr RuntimeController::Clone() const { isolate_snapshot_, // shared_snapshot_, // task_runners_, // - snapshot_delegate_, // io_manager_, // image_decoder_, // advisory_script_uri_, // diff --git a/runtime/runtime_controller.h b/runtime/runtime_controller.h index c3b3e35fa064c..845bc45ef3b77 100644 --- a/runtime/runtime_controller.h +++ b/runtime/runtime_controller.h @@ -33,7 +33,6 @@ class RuntimeController final : public WindowClient { fml::RefPtr isolate_snapshot, fml::RefPtr shared_snapshot, TaskRunners task_runners, - fml::WeakPtr snapshot_delegate, fml::WeakPtr io_manager, fml::WeakPtr iamge_decoder, std::string advisory_script_uri, @@ -129,7 +128,6 @@ class RuntimeController final : public WindowClient { fml::RefPtr isolate_snapshot_; fml::RefPtr shared_snapshot_; TaskRunners task_runners_; - fml::WeakPtr snapshot_delegate_; fml::WeakPtr io_manager_; fml::WeakPtr image_decoder_; std::string advisory_script_uri_; @@ -146,7 +144,6 @@ class RuntimeController final : public WindowClient { fml::RefPtr isolate_snapshot, fml::RefPtr shared_snapshot, TaskRunners task_runners, - fml::WeakPtr snapshot_delegate, fml::WeakPtr io_manager, fml::WeakPtr image_decoder, std::string advisory_script_uri, diff --git a/shell/common/engine.cc b/shell/common/engine.cc index d2c752a4747df..0612f98d60ee7 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -42,7 +42,6 @@ Engine::Engine(Delegate& delegate, TaskRunners task_runners, Settings settings, std::unique_ptr animator, - fml::WeakPtr snapshot_delegate, fml::WeakPtr io_manager) : delegate_(delegate), settings_(std::move(settings)), @@ -62,7 +61,6 @@ Engine::Engine(Delegate& delegate, std::move(isolate_snapshot), // isolate snapshot std::move(shared_snapshot), // shared snapshot std::move(task_runners), // task runners - std::move(snapshot_delegate), // snapshot delegate std::move(io_manager), // io manager image_decoder_.GetWeakPtr(), // image decoder settings_.advisory_script_uri, // advisory script uri diff --git a/shell/common/engine.h b/shell/common/engine.h index 95739c9b2bf61..00c5b9ac724f5 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h @@ -15,7 +15,6 @@ #include "flutter/lib/ui/painting/image_decoder.h" #include "flutter/lib/ui/semantics/custom_accessibility_action.h" #include "flutter/lib/ui/semantics/semantics_node.h" -#include "flutter/lib/ui/snapshot_delegate.h" #include "flutter/lib/ui/text/font_collection.h" #include "flutter/lib/ui/window/platform_message.h" #include "flutter/lib/ui/window/viewport_metrics.h" @@ -67,7 +66,6 @@ class Engine final : public RuntimeDelegate { TaskRunners task_runners, Settings settings, std::unique_ptr animator, - fml::WeakPtr snapshot_delegate, fml::WeakPtr io_manager); ~Engine() override; diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 0d644e15b4a61..0d3cbcd0a11e8 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -53,10 +53,6 @@ fml::WeakPtr Rasterizer::GetWeakPtr() const { return weak_factory_.GetWeakPtr(); } -fml::WeakPtr Rasterizer::GetSnapshotDelegate() const { - return weak_factory_.GetWeakPtr(); -} - void Rasterizer::Setup(std::unique_ptr surface) { surface_ = std::move(surface); compositor_context_->OnGrContextCreated(); @@ -119,58 +115,6 @@ void Rasterizer::Draw(fml::RefPtr> pipeline) { } } -sk_sp Rasterizer::MakeRasterSnapshot(sk_sp picture, - SkISize picture_size) { - TRACE_EVENT0("flutter", __FUNCTION__); - - sk_sp surface; - SkImageInfo image_info = SkImageInfo::MakeN32Premul( - picture_size.width(), picture_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 - ); - } - - if (surface == nullptr || surface->getCanvas() == nullptr) { - return nullptr; - } - - surface->getCanvas()->drawPicture(picture.get()); - - surface->getCanvas()->flush(); - - sk_sp device_snapshot; - { - TRACE_EVENT0("flutter", "MakeDeviceSnpashot"); - device_snapshot = surface->makeImageSnapshot(); - } - - if (device_snapshot == nullptr) { - return nullptr; - } - - { - TRACE_EVENT0("flutter", "DeviceHostTransfer"); - if (auto raster_image = device_snapshot->makeRasterImage()) { - return raster_image; - } - } - - return nullptr; -} - void Rasterizer::DoDraw(std::unique_ptr layer_tree) { FML_DCHECK(task_runners_.GetGPUTaskRunner()->RunsTasksOnCurrentThread()); diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 040e4ae67bdfd..d1d43abf19779 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -14,14 +14,13 @@ #include "flutter/fml/closure.h" #include "flutter/fml/memory/weak_ptr.h" #include "flutter/fml/synchronization/waitable_event.h" -#include "flutter/lib/ui/snapshot_delegate.h" #include "flutter/shell/common/pipeline.h" #include "flutter/shell/common/surface.h" namespace flutter { /// Takes |LayerTree|s and draws its contents. -class Rasterizer final : public SnapshotDelegate { +class Rasterizer final { public: class Delegate { public: @@ -53,8 +52,6 @@ class Rasterizer final : public SnapshotDelegate { fml::WeakPtr GetWeakPtr() const; - fml::WeakPtr GetSnapshotDelegate() const; - flutter::LayerTree* GetLastLayerTree(); void DrawLastLayerTree(); @@ -103,10 +100,6 @@ class Rasterizer final : public SnapshotDelegate { fml::closure next_frame_callback_; fml::WeakPtrFactory weak_factory_; - // |SnapshotDelegate| - sk_sp MakeRasterSnapshot(sk_sp picture, - SkISize picture_size) override; - void DoDraw(std::unique_ptr layer_tree); RasterStatus DrawToSurface(flutter::LayerTree& layer_tree); diff --git a/shell/common/shell.cc b/shell/common/shell.cc index ba217e2af74cf..0377cc91e839d 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -88,18 +88,15 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( // Create the rasterizer on the GPU thread. fml::AutoResetWaitableEvent gpu_latch; std::unique_ptr rasterizer; - fml::WeakPtr snapshot_delegate; fml::TaskRunner::RunNowOrPostTask( task_runners.GetGPUTaskRunner(), [&gpu_latch, // &rasterizer, // on_create_rasterizer, // - shell = shell.get(), // - &snapshot_delegate // + shell = shell.get() // ]() { TRACE_EVENT0("flutter", "ShellSetupGPUSubsystem"); if (auto new_rasterizer = on_create_rasterizer(*shell)) { rasterizer = std::move(new_rasterizer); - snapshot_delegate = rasterizer->GetSnapshotDelegate(); } gpu_latch.Signal(); }); @@ -111,14 +108,13 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( std::unique_ptr engine; fml::TaskRunner::RunNowOrPostTask( shell->GetTaskRunners().GetUITaskRunner(), - fml::MakeCopyable([&ui_latch, // - &engine, // - shell = shell.get(), // - isolate_snapshot = std::move(isolate_snapshot), // - shared_snapshot = std::move(shared_snapshot), // - vsync_waiter = std::move(vsync_waiter), // - snapshot_delegate = std::move(snapshot_delegate), // - io_manager = io_manager->GetWeakPtr() // + fml::MakeCopyable([&ui_latch, // + &engine, // + shell = shell.get(), // + isolate_snapshot = std::move(isolate_snapshot), // + shared_snapshot = std::move(shared_snapshot), // + vsync_waiter = std::move(vsync_waiter), // + io_manager = io_manager->GetWeakPtr() // ]() mutable { TRACE_EVENT0("flutter", "ShellSetupUISubsystem"); const auto& task_runners = shell->GetTaskRunners(); @@ -128,15 +124,14 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( auto animator = std::make_unique(*shell, task_runners, std::move(vsync_waiter)); - engine = std::make_unique(*shell, // - *shell->GetDartVM(), // - std::move(isolate_snapshot), // - std::move(shared_snapshot), // - task_runners, // - shell->GetSettings(), // - std::move(animator), // - std::move(snapshot_delegate), // - std::move(io_manager) // + engine = std::make_unique(*shell, // + *shell->GetDartVM(), // + std::move(isolate_snapshot), // + std::move(shared_snapshot), // + task_runners, // + shell->GetSettings(), // + std::move(animator), // + std::move(io_manager) // ); ui_latch.Signal(); })); diff --git a/testing/dart/canvas_test.dart b/testing/dart/canvas_test.dart index 97c540360c0ab..652eeba91223c 100644 --- a/testing/dart/canvas_test.dart +++ b/testing/dart/canvas_test.dart @@ -4,7 +4,10 @@ import 'dart:typed_data'; import 'dart:ui'; +import 'dart:io'; +import 'package:image/image.dart' as dart_image; +import 'package:path/path.dart' as path; import 'package:test/test.dart'; typedef CanvasCallback = void Function(Canvas canvas); @@ -15,7 +18,7 @@ void testCanvas(CanvasCallback callback) { } catch (error) { } // ignore: empty_catches } -void main() { +void testNoCrashes() { test('canvas APIs should not crash', () async { final Paint paint = Paint(); const Rect rect = Rect.fromLTRB(double.nan, double.nan, double.nan, double.nan); @@ -81,3 +84,71 @@ void main() { testCanvas((Canvas canvas) => canvas.translate(double.nan, double.nan)); }); } + +/// @returns true When the images are resonably similar. +/// @todo Make the search actually fuzzy to a certain degree. +Future fuzzyCompareImages(Image golden, Image img) async { + if (golden.width != img.width || golden.height != img.height) { + return false; + } + int getPixel(ByteData data, int x, int y) => data.getUint32((x + y * golden.width) * 4); + final ByteData goldenData = await golden.toByteData(); + final ByteData imgData = await img.toByteData(); + for (int y = 0; y < golden.height; y++) { + for (int x = 0; x < golden.width; x++) { + if (getPixel(goldenData, x, y) != getPixel(imgData, x, y)) { + return false; + } + } + } + return true; +} + +/// @returns true When the images are resonably similar. +Future fuzzyGoldenImageCompare( + Image image, String goldenImageName) async { + final String imagesPath = path.join('flutter', 'testing', 'resources'); + final File file = File(path.join(imagesPath, goldenImageName)); + final Uint8List goldenData = await file.readAsBytes(); + + final Codec codec = await instantiateImageCodec(goldenData); + final FrameInfo frame = await codec.getNextFrame(); + expect(frame.image.height, equals(image.width)); + expect(frame.image.width, equals(image.height)); + + final bool areEqual = await fuzzyCompareImages(frame.image, image); + if (!areEqual) { + final ByteData pngData = await image.toByteData(); + final ByteBuffer buffer = pngData.buffer; + final dart_image.Image png = dart_image.Image.fromBytes( + image.width, image.height, buffer.asUint8List()); + final String outPath = path.join(imagesPath, 'found_' + goldenImageName); + File(outPath)..writeAsBytesSync(dart_image.encodePng(png)); + print('wrote: ' + outPath); + } + return areEqual; +} + +void main() { + testNoCrashes(); + + test('Simple .toImage', () async { + final PictureRecorder recorder = PictureRecorder(); + final Canvas canvas = Canvas(recorder); + final Path circlePath = Path() + ..addOval( + Rect.fromCircle(center: const Offset(40.0, 40.0), radius: 20.0)); + final Paint paint = Paint() + ..isAntiAlias = false + ..style = PaintingStyle.fill; + canvas.drawPath(circlePath, paint); + final Picture picture = recorder.endRecording(); + final Image image = await picture.toImage(100, 100); + expect(image.width, equals(100)); + expect(image.height, equals(100)); + + final bool areEqual = + await fuzzyGoldenImageCompare(image, 'canvas_test_toImage.png'); + expect(areEqual, true); + }); +} diff --git a/testing/dart/pubspec.yaml b/testing/dart/pubspec.yaml index 1c06c331bf831..2d6e17fd92982 100644 --- a/testing/dart/pubspec.yaml +++ b/testing/dart/pubspec.yaml @@ -2,6 +2,7 @@ name: engine_tests dependencies: test: 1.3.0 path: 1.6.2 + image: ^2.1.4 dependency_overrides: sky_engine: diff --git a/testing/resources/canvas_test_toImage.png b/testing/resources/canvas_test_toImage.png new file mode 100644 index 0000000000000..75d02c2fa967c Binary files /dev/null and b/testing/resources/canvas_test_toImage.png differ