Skip to content

Commit

Permalink
[Impeller] toImageSync for Impeller (flutter#36365)
Browse files Browse the repository at this point in the history
  • Loading branch information
dnfield authored Sep 23, 2022
1 parent 2604b18 commit aec5392
Show file tree
Hide file tree
Showing 15 changed files with 473 additions and 87 deletions.
6 changes: 4 additions & 2 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1023,8 +1023,10 @@ FILE: ../../../flutter/lib/ui/painting/codec.cc
FILE: ../../../flutter/lib/ui/painting/codec.h
FILE: ../../../flutter/lib/ui/painting/color_filter.cc
FILE: ../../../flutter/lib/ui/painting/color_filter.h
FILE: ../../../flutter/lib/ui/painting/display_list_deferred_image_gpu.cc
FILE: ../../../flutter/lib/ui/painting/display_list_deferred_image_gpu.h
FILE: ../../../flutter/lib/ui/painting/display_list_deferred_image_gpu_impeller.cc
FILE: ../../../flutter/lib/ui/painting/display_list_deferred_image_gpu_impeller.h
FILE: ../../../flutter/lib/ui/painting/display_list_deferred_image_gpu_skia.cc
FILE: ../../../flutter/lib/ui/painting/display_list_deferred_image_gpu_skia.h
FILE: ../../../flutter/lib/ui/painting/display_list_image_gpu.cc
FILE: ../../../flutter/lib/ui/painting/display_list_image_gpu.h
FILE: ../../../flutter/lib/ui/painting/engine_layer.cc
Expand Down
6 changes: 4 additions & 2 deletions lib/ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ source_set("ui") {
"painting/codec.h",
"painting/color_filter.cc",
"painting/color_filter.h",
"painting/display_list_deferred_image_gpu.cc",
"painting/display_list_deferred_image_gpu.h",
"painting/display_list_deferred_image_gpu_skia.cc",
"painting/display_list_deferred_image_gpu_skia.h",
"painting/display_list_image_gpu.cc",
"painting/display_list_image_gpu.h",
"painting/engine_layer.cc",
Expand Down Expand Up @@ -163,6 +163,8 @@ source_set("ui") {

if (impeller_supports_rendering) {
sources += [
"painting/display_list_deferred_image_gpu_impeller.cc",
"painting/display_list_deferred_image_gpu_impeller.h",
"painting/image_decoder_impeller.cc",
"painting/image_decoder_impeller.h",
]
Expand Down
37 changes: 31 additions & 6 deletions lib/ui/compositing/scene.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
#include "flutter/lib/ui/compositing/scene.h"

#include "flutter/fml/trace_event.h"
#include "flutter/lib/ui/painting/display_list_deferred_image_gpu.h"
#include "flutter/lib/ui/painting/display_list_deferred_image_gpu_skia.h"
#include "flutter/lib/ui/painting/image.h"
#include "flutter/lib/ui/painting/picture.h"
#include "flutter/lib/ui/ui_dart_state.h"
#include "flutter/lib/ui/window/platform_configuration.h"
#include "flutter/lib/ui/window/window.h"
#if IMPELLER_SUPPORTS_RENDERING
#include "flutter/lib/ui/painting/display_list_deferred_image_gpu_impeller.h"
#endif // IMPELLER_SUPPORTS_RENDERING
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/tonic/converter/dart_converter.h"
Expand Down Expand Up @@ -87,6 +90,29 @@ Dart_Handle Scene::toImage(uint32_t width,
height, raw_image_callback);
}

static sk_sp<DlImage> CreateDeferredImage(
bool impeller,
std::shared_ptr<LayerTree> layer_tree,
uint32_t width,
uint32_t height,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::RefPtr<fml::TaskRunner> raster_task_runner,
fml::RefPtr<SkiaUnrefQueue> unref_queue) {
#if IMPELLER_SUPPORTS_RENDERING
if (impeller) {
return DlDeferredImageGPUImpeller::Make(
std::move(layer_tree), SkISize::Make(width, height),
std::move(snapshot_delegate), std::move(raster_task_runner));
}
#endif // IMPELLER_SUPPORTS_RENDERING

const SkImageInfo image_info = SkImageInfo::Make(
width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
return DlDeferredImageGPUSkia::MakeFromLayerTree(
image_info, std::move(layer_tree), std::move(snapshot_delegate),
std::move(raster_task_runner), std::move(unref_queue));
}

void Scene::RasterizeToImage(uint32_t width,
uint32_t height,
Dart_Handle raw_image_handle) {
Expand All @@ -99,11 +125,10 @@ void Scene::RasterizeToImage(uint32_t width,
auto raster_task_runner = dart_state->GetTaskRunners().GetRasterTaskRunner();

auto image = CanvasImage::Create();
const SkImageInfo image_info = SkImageInfo::Make(
width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
auto dl_image = DlDeferredImageGPU::MakeFromLayerTree(
image_info, std::move(layer_tree_), std::move(snapshot_delegate),
std::move(raster_task_runner), std::move(unref_queue));
auto dl_image = CreateDeferredImage(
dart_state->IsImpellerEnabled(), layer_tree_, width, height,
std::move(snapshot_delegate), std::move(raster_task_runner),
std::move(unref_queue));
image->set_image(dl_image);
image->AssociateWithDartWrapper(raw_image_handle);
}
Expand Down
188 changes: 188 additions & 0 deletions lib/ui/painting/display_list_deferred_image_gpu_impeller.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
// 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.

#include "flutter/lib/ui/painting/display_list_deferred_image_gpu_impeller.h"
#include "display_list_deferred_image_gpu_impeller.h"

namespace flutter {

sk_sp<DlDeferredImageGPUImpeller> DlDeferredImageGPUImpeller::Make(
std::shared_ptr<LayerTree> layer_tree,
const SkISize& size,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::RefPtr<fml::TaskRunner> raster_task_runner) {
return sk_sp<DlDeferredImageGPUImpeller>(new DlDeferredImageGPUImpeller(
DlDeferredImageGPUImpeller::ImageWrapper::Make(
std::move(layer_tree), size, std::move(snapshot_delegate),
std::move(raster_task_runner))));
}

sk_sp<DlDeferredImageGPUImpeller> DlDeferredImageGPUImpeller::Make(
sk_sp<DisplayList> display_list,
const SkISize& size,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::RefPtr<fml::TaskRunner> raster_task_runner) {
return sk_sp<DlDeferredImageGPUImpeller>(new DlDeferredImageGPUImpeller(
DlDeferredImageGPUImpeller::ImageWrapper::Make(
std::move(display_list), size, std::move(snapshot_delegate),
std::move(raster_task_runner))));
}

DlDeferredImageGPUImpeller::DlDeferredImageGPUImpeller(
std::shared_ptr<ImageWrapper> wrapper)
: wrapper_(wrapper) {}

// |DlImage|
DlDeferredImageGPUImpeller::~DlDeferredImageGPUImpeller() = default;

// |DlImage|
sk_sp<SkImage> DlDeferredImageGPUImpeller::skia_image() const {
return nullptr;
};

// |DlImage|
std::shared_ptr<impeller::Texture>
DlDeferredImageGPUImpeller::impeller_texture() const {
if (!wrapper_) {
return nullptr;
}
return wrapper_->texture();
}

// |DlImage|
bool DlDeferredImageGPUImpeller::isOpaque() const {
// Impeller doesn't currently implement opaque alpha types.
return false;
}

// |DlImage|
bool DlDeferredImageGPUImpeller::isTextureBacked() const {
return wrapper_ && wrapper_->isTextureBacked();
}

// |DlImage|
SkISize DlDeferredImageGPUImpeller::dimensions() const {
if (!wrapper_) {
return SkISize::MakeEmpty();
}
return wrapper_->size();
}

// |DlImage|
size_t DlDeferredImageGPUImpeller::GetApproximateByteSize() const {
auto size = sizeof(DlDeferredImageGPUImpeller);
if (wrapper_) {
if (wrapper_->texture()) {
size += wrapper_->texture()
->GetTextureDescriptor()
.GetByteSizeOfBaseMipLevel();
} else {
size += wrapper_->size().width() * wrapper_->size().height() * 4;
}
}
return size;
}

std::shared_ptr<DlDeferredImageGPUImpeller::ImageWrapper>
DlDeferredImageGPUImpeller::ImageWrapper::Make(
sk_sp<DisplayList> display_list,
const SkISize& size,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::RefPtr<fml::TaskRunner> raster_task_runner) {
auto wrapper = std::shared_ptr<ImageWrapper>(new ImageWrapper(
std::move(display_list), size, std::move(snapshot_delegate),
std::move(raster_task_runner)));
wrapper->SnapshotDisplayList();
return wrapper;
}

std::shared_ptr<DlDeferredImageGPUImpeller::ImageWrapper>
DlDeferredImageGPUImpeller::ImageWrapper::Make(
std::shared_ptr<LayerTree> layer_tree,
const SkISize& size,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::RefPtr<fml::TaskRunner> raster_task_runner) {
auto wrapper = std::shared_ptr<ImageWrapper>(
new ImageWrapper(nullptr, size, std::move(snapshot_delegate),
std::move(raster_task_runner)));
wrapper->SnapshotDisplayList(std::move(layer_tree));
return wrapper;
}

DlDeferredImageGPUImpeller::ImageWrapper::ImageWrapper(
sk_sp<DisplayList> display_list,
const SkISize& size,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::RefPtr<fml::TaskRunner> raster_task_runner)
: size_(size),
display_list_(std::move(display_list)),
snapshot_delegate_(std::move(snapshot_delegate)),
raster_task_runner_(std::move(raster_task_runner)) {}

DlDeferredImageGPUImpeller::ImageWrapper::~ImageWrapper() {
fml::TaskRunner::RunNowOrPostTask(
raster_task_runner_, [id = reinterpret_cast<uintptr_t>(this),
texture_registry = std::move(texture_registry_)]() {
if (texture_registry) {
texture_registry->UnregisterContextListener(id);
}
});
}

void DlDeferredImageGPUImpeller::ImageWrapper::OnGrContextCreated() {
FML_DCHECK(raster_task_runner_->RunsTasksOnCurrentThread());
SnapshotDisplayList();
}

void DlDeferredImageGPUImpeller::ImageWrapper::OnGrContextDestroyed() {
// Impeller textures do not have threading requirements for deletion, and
texture_.reset();
}

bool DlDeferredImageGPUImpeller::ImageWrapper::isTextureBacked() const {
return texture_ && texture_->IsValid();
}

void DlDeferredImageGPUImpeller::ImageWrapper::SnapshotDisplayList(
std::shared_ptr<LayerTree> layer_tree) {
fml::TaskRunner::RunNowOrPostTask(
raster_task_runner_,
[weak_this = weak_from_this(), layer_tree = std::move(layer_tree)] {
TRACE_EVENT0("flutter", "SnapshotDisplayList (impeller)");
auto wrapper = weak_this.lock();
if (!wrapper) {
return;
}
auto snapshot_delegate = wrapper->snapshot_delegate_;
if (!snapshot_delegate) {
return;
}

wrapper->texture_registry_ = snapshot_delegate->GetTextureRegistry();
wrapper->texture_registry_->RegisterContextListener(
reinterpret_cast<uintptr_t>(wrapper.get()), weak_this);

if (layer_tree) {
wrapper->display_list_ = layer_tree->Flatten(
SkRect::MakeWH(wrapper->size_.width(), wrapper->size_.height()),
wrapper->texture_registry_);
}
auto snapshot = snapshot_delegate->MakeRasterSnapshot(
wrapper->display_list_, wrapper->size_);
if (!snapshot) {
std::scoped_lock lock(wrapper->error_mutex_);
wrapper->error_ = "Failed to create snapshot.";
return;
}
wrapper->texture_ = snapshot->impeller_texture();
});
}

std::optional<std::string>
DlDeferredImageGPUImpeller::ImageWrapper::get_error() {
std::scoped_lock lock(error_mutex_);
return error_;
}

} // namespace flutter
Loading

0 comments on commit aec5392

Please sign in to comment.