Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,7 @@ FILE: ../../../flutter/lib/ui/isolate_name_server/isolate_name_server_natives.cc
FILE: ../../../flutter/lib/ui/isolate_name_server/isolate_name_server_natives.h
FILE: ../../../flutter/lib/ui/plugins/callback_cache.cc
FILE: ../../../flutter/lib/ui/plugins/callback_cache.h
FILE: ../../../flutter/lib/ui/snapshot_delegate.h
FILE: ../../../flutter/runtime/dart_service_isolate_unittests.cc
FILE: ../../../flutter/shell/common/isolate_configuration.cc
FILE: ../../../flutter/shell/common/isolate_configuration.h
Expand Down
3 changes: 2 additions & 1 deletion lib/ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ source_set("ui") {
"painting/canvas.h",
"painting/codec.cc",
"painting/codec.h",
"painting/engine_layer.h",
"painting/engine_layer.cc",
"painting/engine_layer.h",
"painting/frame_info.cc",
"painting/frame_info.h",
"painting/gradient.cc",
Expand Down Expand Up @@ -65,6 +65,7 @@ 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",
Expand Down
139 changes: 51 additions & 88 deletions lib/ui/compositing/scene.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,46 +53,6 @@ void Scene::dispose() {
ClearDartWrapper();
}

static sk_sp<SkImage> CreateSceneSnapshot(GrContext* context,
sk_sp<SkPicture> picture,
const SkSize& size) {
TRACE_EVENT0("flutter", "CreateSceneSnapshot");
auto image_info =
SkImageInfo::MakeN32Premul(SkISize::Make(size.width(), size.height()));

sk_sp<SkSurface> surface;

if (context) {
surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, image_info);
}

if (!surface) {
surface = SkSurface::MakeRaster(image_info);
}

if (!surface) {
return nullptr;
}

auto canvas = surface->getCanvas();

if (!canvas) {
return nullptr;
}

if (picture) {
canvas->drawPicture(picture.get());
}

auto snapshot = surface->makeImageSnapshot();

if (!snapshot) {
return nullptr;
}

return snapshot->makeRasterImage();
}

Dart_Handle Scene::toImage(uint32_t width,
uint32_t height,
Dart_Handle raw_image_callback) {
Expand All @@ -110,67 +70,70 @@ Dart_Handle Scene::toImage(uint32_t width,
}

auto dart_state = UIDartState::Current();

auto image_callback = std::make_unique<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();

// 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
// thread owns the sole reference to the layer tree. So we flatten the layer
// tree into a picture and use that as the thread transport mechanism.

auto bounds_size = SkSize::Make(width, height);
auto picture = m_layerTree->Flatten(SkRect::MakeSize(bounds_size));
auto picture_bounds = SkISize::Make(width, height);
auto picture = m_layerTree->Flatten(SkRect::MakeWH(width, height));

if (!picture) {
// Already in Dart scope.
return tonic::ToDart("Could not flatten scene into a layer tree.");
}

auto resource_context = dart_state->GetResourceContext();
auto ui_task_runner = dart_state->GetTaskRunners().GetUITaskRunner();
auto unref_queue = dart_state->GetSkiaUnrefQueue();

// The picture has been prepared on the UI thread.
dart_state->GetTaskRunners().GetIOTaskRunner()->PostTask(
fml::MakeCopyable([picture = std::move(picture), //
bounds_size, //
resource_context = std::move(resource_context), //
ui_task_runner = std::move(ui_task_runner), //
image_callback = std::move(image_callback), //
unref_queue = std::move(unref_queue) //
]() mutable {
// Snapshot the picture on the IO thread that contains an optional
// GrContext.
auto image = CreateSceneSnapshot(resource_context.get(),
std::move(picture), bounds_size);

// Send the image back to the UI thread for submission back to the
// framework.
ui_task_runner->PostTask(
fml::MakeCopyable([image = std::move(image), //
image_callback = std::move(image_callback), //
unref_queue = std::move(unref_queue) //
]() mutable {
auto dart_state = image_callback->dart_state().lock();
if (!dart_state) {
// The root isolate could have died in the meantime.
return;
}
tonic::DartState::Scope scope(dart_state);

if (!image) {
tonic::DartInvoke(image_callback->Get(), {Dart_Null()});
return;
}

auto dart_image = CanvasImage::Create();
dart_image->set_image({std::move(image), std::move(unref_queue)});
auto raw_dart_image = tonic::ToDart(std::move(dart_image));

// All done!
tonic::DartInvoke(image_callback->Get(), {raw_dart_image});
}));
}));
auto ui_task = fml::MakeCopyable([ui_task_runner,
image_callback = std::move(image_callback),
unref_queue](
sk_sp<SkImage> raster_image) mutable {
// Send the raster image back to the UI thread for submission to the
// framework.
ui_task_runner->PostTask(fml::MakeCopyable([raster_image,
image_callback =
std::move(image_callback),
unref_queue]() mutable {
auto dart_state = image_callback->dart_state().lock();
if (!dart_state) {
// The root isolate could have died in the meantime.
return;
}
tonic::DartState::Scope scope(dart_state);

if (!raster_image) {
tonic::DartInvoke(image_callback->Get(), {Dart_Null()});
return;
}

auto dart_image = CanvasImage::Create();
dart_image->set_image({std::move(raster_image), std::move(unref_queue)});
auto raw_dart_image = tonic::ToDart(std::move(dart_image));

// All done!
tonic::DartInvoke(image_callback->Get(), {raw_dart_image});
}));
});

auto gpu_task = fml::MakeCopyable([gpu_task_runner, picture, picture_bounds,
snapshot_delegate, ui_task]() {
gpu_task_runner->PostTask([snapshot_delegate, picture, picture_bounds,
ui_task]() {
// Snapshot the picture on the GPU thread. This thread has access to the
// GPU contexts that may contain the sole references to a texture backed
// images in the picture.
ui_task(snapshot_delegate->MakeRasterSnapshot(picture, picture_bounds));
});
});

// Kick things off on the GPU.
gpu_task();

return Dart_Null();
}
Expand Down
21 changes: 21 additions & 0 deletions lib/ui/snapshot_delegate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2018 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 blink {

class SnapshotDelegate {
public:
virtual sk_sp<SkImage> MakeRasterSnapshot(sk_sp<SkPicture> picture,
SkISize picture_size) = 0;
};

} // namespace blink

#endif // FLUTTER_LIB_UI_SNAPSHOT_DELEGATE_H_
6 changes: 6 additions & 0 deletions lib/ui/ui_dart_state.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace blink {
UIDartState::UIDartState(TaskRunners task_runners,
TaskObserverAdd add_callback,
TaskObserverRemove remove_callback,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<GrContext> resource_context,
fml::RefPtr<flow::SkiaUnrefQueue> skia_unref_queue,
std::string advisory_script_uri,
Expand All @@ -25,6 +26,7 @@ UIDartState::UIDartState(TaskRunners task_runners,
: task_runners_(std::move(task_runners)),
add_callback_(std::move(add_callback)),
remove_callback_(std::move(remove_callback)),
snapshot_delegate_(std::move(snapshot_delegate)),
resource_context_(std::move(resource_context)),
advisory_script_uri_(std::move(advisory_script_uri)),
advisory_script_entrypoint_(std::move(advisory_script_entrypoint)),
Expand Down Expand Up @@ -99,6 +101,10 @@ void UIDartState::AddOrRemoveTaskObserver(bool add) {
}
}

fml::WeakPtr<SnapshotDelegate> UIDartState::GetSnapshotDelegate() const {
return snapshot_delegate_;
}

fml::WeakPtr<GrContext> UIDartState::GetResourceContext() const {
return resource_context_;
}
Expand Down
5 changes: 5 additions & 0 deletions lib/ui/ui_dart_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "flutter/fml/build_config.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/lib/ui/isolate_name_server/isolate_name_server.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"
Expand Down Expand Up @@ -47,6 +48,8 @@ class UIDartState : public tonic::DartState {

fml::RefPtr<flow::SkiaUnrefQueue> GetSkiaUnrefQueue() const;

fml::WeakPtr<SnapshotDelegate> GetSnapshotDelegate() const;

fml::WeakPtr<GrContext> GetResourceContext() const;

IsolateNameServer* GetIsolateNameServer();
Expand All @@ -68,6 +71,7 @@ class UIDartState : public tonic::DartState {
UIDartState(TaskRunners task_runners,
TaskObserverAdd add_callback,
TaskObserverRemove remove_callback,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<GrContext> resource_context,
fml::RefPtr<flow::SkiaUnrefQueue> skia_unref_queue,
std::string advisory_script_uri,
Expand All @@ -89,6 +93,7 @@ class UIDartState : public tonic::DartState {
const TaskRunners task_runners_;
const TaskObserverAdd add_callback_;
const TaskObserverRemove remove_callback_;
fml::WeakPtr<SnapshotDelegate> snapshot_delegate_;
fml::WeakPtr<GrContext> resource_context_;
const std::string advisory_script_uri_;
const std::string advisory_script_entrypoint_;
Expand Down
22 changes: 14 additions & 8 deletions runtime/dart_isolate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(
fml::RefPtr<DartSnapshot> shared_snapshot,
TaskRunners task_runners,
std::unique_ptr<Window> window,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<GrContext> resource_context,
fml::RefPtr<flow::SkiaUnrefQueue> unref_queue,
std::string advisory_script_uri,
Expand All @@ -54,14 +55,15 @@ std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(
// isolate lifecycle is entirely managed by the VM).
auto root_embedder_data = std::make_unique<std::shared_ptr<DartIsolate>>(
std::make_shared<DartIsolate>(
vm, // VM
std::move(isolate_snapshot), // isolate snapshot
std::move(shared_snapshot), // shared snapshot
task_runners, // task runners
std::move(resource_context), // resource context
std::move(unref_queue), // skia unref queue
advisory_script_uri, // advisory URI
advisory_script_entrypoint, // advisory entrypoint
vm, // VM
std::move(isolate_snapshot), // isolate snapshot
std::move(shared_snapshot), // shared snapshot
task_runners, // task runners
std::move(snapshot_delegate), // snapshot delegate
std::move(resource_context), // resource context
std::move(unref_queue), // skia unref queue
advisory_script_uri, // advisory URI
advisory_script_entrypoint, // advisory entrypoint
nullptr // child isolate preparer will be set when this isolate is
// prepared to run
));
Expand Down Expand Up @@ -101,6 +103,7 @@ DartIsolate::DartIsolate(DartVM* vm,
fml::RefPtr<DartSnapshot> isolate_snapshot,
fml::RefPtr<DartSnapshot> shared_snapshot,
TaskRunners task_runners,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<GrContext> resource_context,
fml::RefPtr<flow::SkiaUnrefQueue> unref_queue,
std::string advisory_script_uri,
Expand All @@ -109,6 +112,7 @@ DartIsolate::DartIsolate(DartVM* vm,
: UIDartState(std::move(task_runners),
vm->GetSettings().task_observer_add,
vm->GetSettings().task_observer_remove,
std::move(snapshot_delegate),
std::move(resource_context),
std::move(unref_queue),
advisory_script_uri,
Expand Down Expand Up @@ -520,6 +524,7 @@ Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate(
vm->GetSharedSnapshot(), // shared snapshot
null_task_runners, // task runners
nullptr, // window
{}, // snapshot delegate
{}, // resource context
{}, // unref queue
advisory_script_uri == nullptr ? ""
Expand Down Expand Up @@ -630,6 +635,7 @@ 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<GrContext>{}, // resource_context
nullptr, // unref_queue
advisory_script_uri, // advisory_script_uri
Expand Down
3 changes: 3 additions & 0 deletions runtime/dart_isolate.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "flutter/fml/compiler_specific.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/mapping.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"
Expand Down Expand Up @@ -44,6 +45,7 @@ class DartIsolate : public UIDartState {
fml::RefPtr<DartSnapshot> shared_snapshot,
TaskRunners task_runners,
std::unique_ptr<Window> window,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<GrContext> resource_context,
fml::RefPtr<flow::SkiaUnrefQueue> unref_queue,
std::string advisory_script_uri,
Expand All @@ -54,6 +56,7 @@ class DartIsolate : public UIDartState {
fml::RefPtr<DartSnapshot> isolate_snapshot,
fml::RefPtr<DartSnapshot> shared_snapshot,
TaskRunners task_runners,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<GrContext> resource_context,
fml::RefPtr<flow::SkiaUnrefQueue> unref_queue,
std::string advisory_script_uri,
Expand Down
2 changes: 2 additions & 0 deletions runtime/dart_isolate_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ TEST_F(DartIsolateTest, RootIsolateCreationAndShutdown) {
vm->GetSharedSnapshot(), // shared snapshot
std::move(task_runners), // task runners
nullptr, // window
{}, // snapshot delegate
{}, // resource context
nullptr, // unref qeueue
"main.dart", // advisory uri
Expand Down Expand Up @@ -64,6 +65,7 @@ TEST_F(DartIsolateTest, IsolateShutdownCallbackIsInIsolateScope) {
vm->GetSharedSnapshot(), // shared snapshot
std::move(task_runners), // task runners
nullptr, // window
{}, // snapshot delegate
{}, // resource context
nullptr, // unref qeueue
"main.dart", // advisory uri
Expand Down
Loading