未验证 提交 78a8ca0f 编写于 作者: G gaaclarke 提交者: GitHub

Made Picture::toImage happen on the IO thread with no need for an onscreen surface. (#9813)

Made Picture::toImage happen on the IO thread with no need for a surface.
上级 74af88ba
......@@ -403,7 +403,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
......
......@@ -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",
......
......@@ -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<SkSurface> MakeSnapshotSurface(const SkISize& picture_size,
fml::WeakPtr<GrContext> 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<SkImage> MakeRasterSnapshot(sk_sp<SkPicture> picture,
sk_sp<SkSurface> 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<SkImage> 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<SkPicture> 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<GrContext> 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<SkPicture> 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<SkImage> 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<SkSurface> surface =
MakeSnapshotSurface(picture_bounds, resource_context);
sk_sp<SkImage> raster_image = MakeRasterSnapshot(picture, surface);
fml::TaskRunner::RunNowOrPostTask(
ui_task_runner, [ui_task, raster_image]() { ui_task(raster_image); });
});
return Dart_Null();
}
......
// 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<SkImage> MakeRasterSnapshot(sk_sp<SkPicture> picture,
SkISize picture_size) = 0;
};
} // namespace flutter
#endif // FLUTTER_LIB_UI_SNAPSHOT_DELEGATE_H_
......@@ -17,7 +17,6 @@ UIDartState::UIDartState(
TaskRunners task_runners,
TaskObserverAdd add_callback,
TaskObserverRemove remove_callback,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<IOManager> io_manager,
fml::WeakPtr<ImageDecoder> 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<SnapshotDelegate> UIDartState::GetSnapshotDelegate() const {
return snapshot_delegate_;
}
fml::WeakPtr<GrContext> UIDartState::GetResourceContext() const {
if (!io_manager_) {
return {};
......
......@@ -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<flutter::SkiaUnrefQueue> GetSkiaUnrefQueue() const;
fml::WeakPtr<SnapshotDelegate> GetSnapshotDelegate() const;
fml::WeakPtr<GrContext> GetResourceContext() const;
fml::WeakPtr<ImageDecoder> GetImageDecoder() const;
......@@ -78,7 +75,6 @@ class UIDartState : public tonic::DartState {
UIDartState(TaskRunners task_runners,
TaskObserverAdd add_callback,
TaskObserverRemove remove_callback,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<IOManager> io_manager,
fml::WeakPtr<ImageDecoder> 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<SnapshotDelegate> snapshot_delegate_;
fml::WeakPtr<IOManager> io_manager_;
fml::WeakPtr<ImageDecoder> image_decoder_;
const std::string advisory_script_uri_;
......
......@@ -35,7 +35,6 @@ std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(
fml::RefPtr<const DartSnapshot> shared_snapshot,
TaskRunners task_runners,
std::unique_ptr<Window> window,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<IOManager> io_manager,
fml::WeakPtr<ImageDecoder> image_decoder,
std::string advisory_script_uri,
......@@ -57,18 +56,17 @@ std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(
// being prepared to run.
auto root_embedder_data = std::make_unique<std::shared_ptr<DartIsolate>>(
std::make_shared<DartIsolate>(
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<const DartSnapshot> isolate_snapshot,
fml::RefPtr<const DartSnapshot> shared_snapshot,
TaskRunners task_runners,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<IOManager> io_manager,
fml::WeakPtr<ImageDecoder> 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<SnapshotDelegate>{}, // snapshot_delegate
fml::WeakPtr<IOManager>{}, // io_manager
fml::WeakPtr<ImageDecoder>{}, // io_manager
advisory_script_uri, // advisory_script_uri
......
......@@ -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<const DartSnapshot> shared_snapshot,
TaskRunners task_runners,
std::unique_ptr<Window> window,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<IOManager> io_manager,
fml::WeakPtr<ImageDecoder> image_decoder,
std::string advisory_script_uri,
......@@ -60,7 +58,6 @@ class DartIsolate : public UIDartState {
fml::RefPtr<const DartSnapshot> isolate_snapshot,
fml::RefPtr<const DartSnapshot> shared_snapshot,
TaskRunners task_runners,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<IOManager> io_manager,
fml::WeakPtr<ImageDecoder> image_decoder,
std::string advisory_script_uri,
......
......@@ -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
......
......@@ -56,7 +56,6 @@ static std::shared_ptr<DartIsolate> CreateAndRunRootIsolate(
vm.GetSharedSnapshot(), // shared_snapshot
runners, // task_runners
{}, // window
{}, // snapshot_delegate
{}, // io_manager
{}, // image_decoder
"main.dart", // advisory_script_uri
......
......@@ -20,7 +20,6 @@ RuntimeController::RuntimeController(
fml::RefPtr<const DartSnapshot> p_isolate_snapshot,
fml::RefPtr<const DartSnapshot> p_shared_snapshot,
TaskRunners p_task_runners,
fml::WeakPtr<SnapshotDelegate> p_snapshot_delegate,
fml::WeakPtr<IOManager> p_io_manager,
fml::WeakPtr<ImageDecoder> 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<const DartSnapshot> p_isolate_snapshot,
fml::RefPtr<const DartSnapshot> p_shared_snapshot,
TaskRunners p_task_runners,
fml::WeakPtr<SnapshotDelegate> p_snapshot_delegate,
fml::WeakPtr<IOManager> p_io_manager,
fml::WeakPtr<ImageDecoder> 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<Window>(this), //
snapshot_delegate_, //
io_manager_, //
image_decoder_, //
p_advisory_script_uri, //
......@@ -142,7 +137,6 @@ std::unique_ptr<RuntimeController> RuntimeController::Clone() const {
isolate_snapshot_, //
shared_snapshot_, //
task_runners_, //
snapshot_delegate_, //
io_manager_, //
image_decoder_, //
advisory_script_uri_, //
......
......@@ -33,7 +33,6 @@ class RuntimeController final : public WindowClient {
fml::RefPtr<const DartSnapshot> isolate_snapshot,
fml::RefPtr<const DartSnapshot> shared_snapshot,
TaskRunners task_runners,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<IOManager> io_manager,
fml::WeakPtr<ImageDecoder> iamge_decoder,
std::string advisory_script_uri,
......@@ -129,7 +128,6 @@ class RuntimeController final : public WindowClient {
fml::RefPtr<const DartSnapshot> isolate_snapshot_;
fml::RefPtr<const DartSnapshot> shared_snapshot_;
TaskRunners task_runners_;
fml::WeakPtr<SnapshotDelegate> snapshot_delegate_;
fml::WeakPtr<IOManager> io_manager_;
fml::WeakPtr<ImageDecoder> image_decoder_;
std::string advisory_script_uri_;
......@@ -146,7 +144,6 @@ class RuntimeController final : public WindowClient {
fml::RefPtr<const DartSnapshot> isolate_snapshot,
fml::RefPtr<const DartSnapshot> shared_snapshot,
TaskRunners task_runners,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<IOManager> io_manager,
fml::WeakPtr<ImageDecoder> image_decoder,
std::string advisory_script_uri,
......
......@@ -42,7 +42,6 @@ Engine::Engine(Delegate& delegate,
TaskRunners task_runners,
Settings settings,
std::unique_ptr<Animator> animator,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<IOManager> 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
......
......@@ -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"
......@@ -272,7 +271,6 @@ class Engine final : public RuntimeDelegate {
TaskRunners task_runners,
Settings settings,
std::unique_ptr<Animator> animator,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<IOManager> io_manager);
//----------------------------------------------------------------------------
......
......@@ -53,10 +53,6 @@ fml::WeakPtr<Rasterizer> Rasterizer::GetWeakPtr() const {
return weak_factory_.GetWeakPtr();
}
fml::WeakPtr<SnapshotDelegate> Rasterizer::GetSnapshotDelegate() const {
return weak_factory_.GetWeakPtr();
}
void Rasterizer::Setup(std::unique_ptr<Surface> surface) {
surface_ = std::move(surface);
compositor_context_->OnGrContextCreated();
......@@ -119,58 +115,6 @@ void Rasterizer::Draw(fml::RefPtr<Pipeline<flutter::LayerTree>> pipeline) {
}
}
sk_sp<SkImage> Rasterizer::MakeRasterSnapshot(sk_sp<SkPicture> picture,
SkISize picture_size) {
TRACE_EVENT0("flutter", __FUNCTION__);
sk_sp<SkSurface> 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<SkImage> 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<flutter::LayerTree> layer_tree) {
FML_DCHECK(task_runners_.GetGPUTaskRunner()->RunsTasksOnCurrentThread());
......
......@@ -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<Rasterizer> GetWeakPtr() const;
fml::WeakPtr<SnapshotDelegate> GetSnapshotDelegate() const;
flutter::LayerTree* GetLastLayerTree();
void DrawLastLayerTree();
......@@ -103,10 +100,6 @@ class Rasterizer final : public SnapshotDelegate {
fml::closure next_frame_callback_;
fml::WeakPtrFactory<Rasterizer> weak_factory_;
// |SnapshotDelegate|
sk_sp<SkImage> MakeRasterSnapshot(sk_sp<SkPicture> picture,
SkISize picture_size) override;
void DoDraw(std::unique_ptr<flutter::LayerTree> layer_tree);
RasterStatus DrawToSurface(flutter::LayerTree& layer_tree);
......
......@@ -88,18 +88,15 @@ std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
// Create the rasterizer on the GPU thread.
fml::AutoResetWaitableEvent gpu_latch;
std::unique_ptr<Rasterizer> rasterizer;
fml::WeakPtr<SnapshotDelegate> 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> Shell::CreateShellOnPlatformThread(
std::unique_ptr<Engine> 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> Shell::CreateShellOnPlatformThread(
auto animator = std::make_unique<Animator>(*shell, task_runners,
std::move(vsync_waiter));
engine = std::make_unique<Engine>(*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<Engine>(*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();
}));
......
......@@ -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<bool> 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<bool> 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);
});
}
......@@ -2,6 +2,7 @@ name: engine_tests
dependencies:
test: 1.3.0
path: 1.6.2
image: ^2.1.4
dependency_overrides:
sky_engine:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册