diff --git a/engine/src/flutter/ci/licenses_golden/licenses_flutter b/engine/src/flutter/ci/licenses_golden/licenses_flutter index e1071c3d092..2b61df1e778 100644 --- a/engine/src/flutter/ci/licenses_golden/licenses_flutter +++ b/engine/src/flutter/ci/licenses_golden/licenses_flutter @@ -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 diff --git a/engine/src/flutter/lib/ui/BUILD.gn b/engine/src/flutter/lib/ui/BUILD.gn index fb2d8012419..652fef02b62 100644 --- a/engine/src/flutter/lib/ui/BUILD.gn +++ b/engine/src/flutter/lib/ui/BUILD.gn @@ -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", @@ -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", ] diff --git a/engine/src/flutter/lib/ui/compositing/scene.cc b/engine/src/flutter/lib/ui/compositing/scene.cc index 5a8601b90ef..e06e042cc54 100644 --- a/engine/src/flutter/lib/ui/compositing/scene.cc +++ b/engine/src/flutter/lib/ui/compositing/scene.cc @@ -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" @@ -87,6 +90,29 @@ Dart_Handle Scene::toImage(uint32_t width, height, raw_image_callback); } +static sk_sp CreateDeferredImage( + bool impeller, + std::shared_ptr layer_tree, + uint32_t width, + uint32_t height, + fml::WeakPtr snapshot_delegate, + fml::RefPtr raster_task_runner, + fml::RefPtr 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) { @@ -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); } diff --git a/engine/src/flutter/lib/ui/painting/display_list_deferred_image_gpu_impeller.cc b/engine/src/flutter/lib/ui/painting/display_list_deferred_image_gpu_impeller.cc new file mode 100644 index 00000000000..4bb0268fbd9 --- /dev/null +++ b/engine/src/flutter/lib/ui/painting/display_list_deferred_image_gpu_impeller.cc @@ -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::Make( + std::shared_ptr layer_tree, + const SkISize& size, + fml::WeakPtr snapshot_delegate, + fml::RefPtr raster_task_runner) { + return sk_sp(new DlDeferredImageGPUImpeller( + DlDeferredImageGPUImpeller::ImageWrapper::Make( + std::move(layer_tree), size, std::move(snapshot_delegate), + std::move(raster_task_runner)))); +} + +sk_sp DlDeferredImageGPUImpeller::Make( + sk_sp display_list, + const SkISize& size, + fml::WeakPtr snapshot_delegate, + fml::RefPtr raster_task_runner) { + return sk_sp(new DlDeferredImageGPUImpeller( + DlDeferredImageGPUImpeller::ImageWrapper::Make( + std::move(display_list), size, std::move(snapshot_delegate), + std::move(raster_task_runner)))); +} + +DlDeferredImageGPUImpeller::DlDeferredImageGPUImpeller( + std::shared_ptr wrapper) + : wrapper_(wrapper) {} + +// |DlImage| +DlDeferredImageGPUImpeller::~DlDeferredImageGPUImpeller() = default; + +// |DlImage| +sk_sp DlDeferredImageGPUImpeller::skia_image() const { + return nullptr; +}; + +// |DlImage| +std::shared_ptr +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::Make( + sk_sp display_list, + const SkISize& size, + fml::WeakPtr snapshot_delegate, + fml::RefPtr raster_task_runner) { + auto wrapper = std::shared_ptr(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::Make( + std::shared_ptr layer_tree, + const SkISize& size, + fml::WeakPtr snapshot_delegate, + fml::RefPtr raster_task_runner) { + auto wrapper = std::shared_ptr( + 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 display_list, + const SkISize& size, + fml::WeakPtr snapshot_delegate, + fml::RefPtr 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(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 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(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 +DlDeferredImageGPUImpeller::ImageWrapper::get_error() { + std::scoped_lock lock(error_mutex_); + return error_; +} + +} // namespace flutter diff --git a/engine/src/flutter/lib/ui/painting/display_list_deferred_image_gpu_impeller.h b/engine/src/flutter/lib/ui/painting/display_list_deferred_image_gpu_impeller.h new file mode 100644 index 00000000000..0e722e38c94 --- /dev/null +++ b/engine/src/flutter/lib/ui/painting/display_list_deferred_image_gpu_impeller.h @@ -0,0 +1,119 @@ +// 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. + +#pragma once + +#include "flutter/common/graphics/texture.h" +#include "flutter/display_list/display_list_image.h" +#include "flutter/flow/layers/layer_tree.h" +#include "flutter/fml/macros.h" +#include "flutter/fml/memory/weak_ptr.h" +#include "flutter/fml/task_runner.h" +#include "flutter/lib/ui/snapshot_delegate.h" +#include "impeller/renderer/texture.h" + +namespace flutter { + +class DlDeferredImageGPUImpeller final : public DlImage { + public: + static sk_sp Make( + std::shared_ptr layer_tree, + const SkISize& size, + fml::WeakPtr snapshot_delegate, + fml::RefPtr raster_task_runner); + + static sk_sp Make( + sk_sp display_list, + const SkISize& size, + fml::WeakPtr snapshot_delegate, + fml::RefPtr raster_task_runner); + + // |DlImage| + ~DlDeferredImageGPUImpeller() override; + + // |DlImage| + sk_sp skia_image() const override; + + // |DlImage| + std::shared_ptr impeller_texture() const override; + + // |DlImage| + bool isOpaque() const override; + + // |DlImage| + bool isTextureBacked() const override; + + // |DlImage| + SkISize dimensions() const override; + + // |DlImage| + size_t GetApproximateByteSize() const override; + + private: + class ImageWrapper final : public std::enable_shared_from_this, + public ContextListener { + public: + ~ImageWrapper(); + + static std::shared_ptr Make( + sk_sp display_list, + const SkISize& size, + fml::WeakPtr snapshot_delegate, + fml::RefPtr raster_task_runner); + + static std::shared_ptr Make( + std::shared_ptr layer_tree, + const SkISize& size, + fml::WeakPtr snapshot_delegate, + fml::RefPtr raster_task_runner); + + bool isTextureBacked() const; + + const std::shared_ptr texture() const { + return texture_; + } + + const SkISize size() const { return size_; } + + std::optional get_error(); + + private: + SkISize size_; + sk_sp display_list_; + std::shared_ptr texture_; + fml::WeakPtr snapshot_delegate_; + fml::RefPtr raster_task_runner_; + std::shared_ptr texture_registry_; + + mutable std::mutex error_mutex_; + std::optional error_; + + ImageWrapper(sk_sp display_list, + const SkISize& size, + fml::WeakPtr snapshot_delegate, + fml::RefPtr raster_task_runner); + + // If a layer tree is provided, it will be flattened during the raster + // thread task spwaned by this method. After being flattened into a display + // list, the image wrapper will be updated to hold this display list and the + // layer tree can be dropped. + void SnapshotDisplayList(std::shared_ptr layer_tree = nullptr); + + // |ContextListener| + void OnGrContextCreated() override; + + // |ContextListener| + void OnGrContextDestroyed() override; + + FML_DISALLOW_COPY_AND_ASSIGN(ImageWrapper); + }; + + const std::shared_ptr wrapper_; + + explicit DlDeferredImageGPUImpeller(std::shared_ptr wrapper); + + FML_DISALLOW_COPY_AND_ASSIGN(DlDeferredImageGPUImpeller); +}; + +} // namespace flutter diff --git a/engine/src/flutter/lib/ui/painting/display_list_deferred_image_gpu.cc b/engine/src/flutter/lib/ui/painting/display_list_deferred_image_gpu_skia.cc similarity index 78% rename from engine/src/flutter/lib/ui/painting/display_list_deferred_image_gpu.cc rename to engine/src/flutter/lib/ui/painting/display_list_deferred_image_gpu_skia.cc index 14391c2128a..ab95eac6d33 100644 --- a/engine/src/flutter/lib/ui/painting/display_list_deferred_image_gpu.cc +++ b/engine/src/flutter/lib/ui/painting/display_list_deferred_image_gpu_skia.cc @@ -2,47 +2,46 @@ // 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.h" +#include "flutter/lib/ui/painting/display_list_deferred_image_gpu_skia.h" -#include "display_list_deferred_image_gpu.h" #include "third_party/skia/include/core/SkColorSpace.h" namespace flutter { -sk_sp DlDeferredImageGPU::Make( +sk_sp DlDeferredImageGPUSkia::Make( const SkImageInfo& image_info, sk_sp display_list, fml::WeakPtr snapshot_delegate, fml::RefPtr raster_task_runner, fml::RefPtr unref_queue) { - return sk_sp(new DlDeferredImageGPU( + return sk_sp(new DlDeferredImageGPUSkia( ImageWrapper::Make(image_info, std::move(display_list), std::move(snapshot_delegate), raster_task_runner, std::move(unref_queue)), raster_task_runner)); } -sk_sp DlDeferredImageGPU::MakeFromLayerTree( +sk_sp DlDeferredImageGPUSkia::MakeFromLayerTree( const SkImageInfo& image_info, std::shared_ptr layer_tree, fml::WeakPtr snapshot_delegate, fml::RefPtr raster_task_runner, fml::RefPtr unref_queue) { - return sk_sp(new DlDeferredImageGPU( + return sk_sp(new DlDeferredImageGPUSkia( ImageWrapper::MakeFromLayerTree( image_info, std::move(layer_tree), std::move(snapshot_delegate), raster_task_runner, std::move(unref_queue)), raster_task_runner)); } -DlDeferredImageGPU::DlDeferredImageGPU( +DlDeferredImageGPUSkia::DlDeferredImageGPUSkia( std::shared_ptr image_wrapper, fml::RefPtr raster_task_runner) : image_wrapper_(std::move(image_wrapper)), raster_task_runner_(std::move(raster_task_runner)) {} // |DlImage| -DlDeferredImageGPU::~DlDeferredImageGPU() { +DlDeferredImageGPUSkia::~DlDeferredImageGPUSkia() { fml::TaskRunner::RunNowOrPostTask( raster_task_runner_, [image_wrapper = std::move(image_wrapper_)]() { if (!image_wrapper) { @@ -54,45 +53,45 @@ DlDeferredImageGPU::~DlDeferredImageGPU() { } // |DlImage| -sk_sp DlDeferredImageGPU::skia_image() const { +sk_sp DlDeferredImageGPUSkia::skia_image() const { return image_wrapper_ ? image_wrapper_->CreateSkiaImage() : nullptr; }; // |DlImage| -std::shared_ptr DlDeferredImageGPU::impeller_texture() +std::shared_ptr DlDeferredImageGPUSkia::impeller_texture() const { return nullptr; } // |DlImage| -bool DlDeferredImageGPU::isOpaque() const { +bool DlDeferredImageGPUSkia::isOpaque() const { return image_wrapper_ ? image_wrapper_->image_info().isOpaque() : false; } // |DlImage| -bool DlDeferredImageGPU::isTextureBacked() const { +bool DlDeferredImageGPUSkia::isTextureBacked() const { return image_wrapper_ ? image_wrapper_->isTextureBacked() : false; } // |DlImage| -SkISize DlDeferredImageGPU::dimensions() const { +SkISize DlDeferredImageGPUSkia::dimensions() const { return image_wrapper_ ? image_wrapper_->image_info().dimensions() : SkISize::MakeEmpty(); } // |DlImage| -size_t DlDeferredImageGPU::GetApproximateByteSize() const { +size_t DlDeferredImageGPUSkia::GetApproximateByteSize() const { return sizeof(this) + (image_wrapper_ ? image_wrapper_->image_info().computeMinByteSize() : 0); } -std::optional DlDeferredImageGPU::get_error() const { +std::optional DlDeferredImageGPUSkia::get_error() const { return image_wrapper_ ? image_wrapper_->get_error() : std::nullopt; } -std::shared_ptr -DlDeferredImageGPU::ImageWrapper::Make( +std::shared_ptr +DlDeferredImageGPUSkia::ImageWrapper::Make( const SkImageInfo& image_info, sk_sp display_list, fml::WeakPtr snapshot_delegate, @@ -105,8 +104,8 @@ DlDeferredImageGPU::ImageWrapper::Make( return wrapper; } -std::shared_ptr -DlDeferredImageGPU::ImageWrapper::MakeFromLayerTree( +std::shared_ptr +DlDeferredImageGPUSkia::ImageWrapper::MakeFromLayerTree( const SkImageInfo& image_info, std::shared_ptr layer_tree, fml::WeakPtr snapshot_delegate, @@ -119,7 +118,7 @@ DlDeferredImageGPU::ImageWrapper::MakeFromLayerTree( return wrapper; } -DlDeferredImageGPU::ImageWrapper::ImageWrapper( +DlDeferredImageGPUSkia::ImageWrapper::ImageWrapper( const SkImageInfo& image_info, sk_sp display_list, fml::WeakPtr snapshot_delegate, @@ -131,18 +130,18 @@ DlDeferredImageGPU::ImageWrapper::ImageWrapper( raster_task_runner_(std::move(raster_task_runner)), unref_queue_(std::move(unref_queue)) {} -void DlDeferredImageGPU::ImageWrapper::OnGrContextCreated() { +void DlDeferredImageGPUSkia::ImageWrapper::OnGrContextCreated() { FML_DCHECK(raster_task_runner_->RunsTasksOnCurrentThread()); SnapshotDisplayList(); } -void DlDeferredImageGPU::ImageWrapper::OnGrContextDestroyed() { +void DlDeferredImageGPUSkia::ImageWrapper::OnGrContextDestroyed() { FML_DCHECK(raster_task_runner_->RunsTasksOnCurrentThread()); DeleteTexture(); } -sk_sp DlDeferredImageGPU::ImageWrapper::CreateSkiaImage() const { +sk_sp DlDeferredImageGPUSkia::ImageWrapper::CreateSkiaImage() const { FML_DCHECK(raster_task_runner_->RunsTasksOnCurrentThread()); if (texture_.isValid() && context_) { @@ -154,11 +153,11 @@ sk_sp DlDeferredImageGPU::ImageWrapper::CreateSkiaImage() const { return image_; } -bool DlDeferredImageGPU::ImageWrapper::isTextureBacked() const { +bool DlDeferredImageGPUSkia::ImageWrapper::isTextureBacked() const { return texture_.isValid(); } -void DlDeferredImageGPU::ImageWrapper::SnapshotDisplayList( +void DlDeferredImageGPUSkia::ImageWrapper::SnapshotDisplayList( std::shared_ptr layer_tree) { fml::TaskRunner::RunNowOrPostTask( raster_task_runner_, @@ -179,8 +178,8 @@ void DlDeferredImageGPU::ImageWrapper::SnapshotDisplayList( snapshot_delegate->GetGrContext()); wrapper->display_list_ = std::move(display_list); } - auto result = snapshot_delegate->MakeGpuImage(wrapper->display_list_, - wrapper->image_info_); + auto result = snapshot_delegate->MakeSkiaGpuImage( + wrapper->display_list_, wrapper->image_info_); if (result->texture.isValid()) { wrapper->texture_ = result->texture; wrapper->context_ = std::move(result->context); @@ -197,19 +196,19 @@ void DlDeferredImageGPU::ImageWrapper::SnapshotDisplayList( }); } -std::optional DlDeferredImageGPU::ImageWrapper::get_error() { +std::optional DlDeferredImageGPUSkia::ImageWrapper::get_error() { std::scoped_lock lock(error_mutex_); return error_; } -void DlDeferredImageGPU::ImageWrapper::Unregister() { +void DlDeferredImageGPUSkia::ImageWrapper::Unregister() { if (texture_registry_) { texture_registry_->UnregisterContextListener( reinterpret_cast(this)); } } -void DlDeferredImageGPU::ImageWrapper::DeleteTexture() { +void DlDeferredImageGPUSkia::ImageWrapper::DeleteTexture() { if (texture_.isValid()) { unref_queue_->DeleteTexture(std::move(texture_)); texture_ = GrBackendTexture(); diff --git a/engine/src/flutter/lib/ui/painting/display_list_deferred_image_gpu.h b/engine/src/flutter/lib/ui/painting/display_list_deferred_image_gpu_skia.h similarity index 91% rename from engine/src/flutter/lib/ui/painting/display_list_deferred_image_gpu.h rename to engine/src/flutter/lib/ui/painting/display_list_deferred_image_gpu_skia.h index 5f04eb25d07..0cb5bddfbcd 100644 --- a/engine/src/flutter/lib/ui/painting/display_list_deferred_image_gpu.h +++ b/engine/src/flutter/lib/ui/painting/display_list_deferred_image_gpu_skia.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FLUTTER_LIB_UI_PAINTING_DISPLAY_LIST_DEFERRED_IMAGE_GPU_H_ -#define FLUTTER_LIB_UI_PAINTING_DISPLAY_LIST_DEFERRED_IMAGE_GPU_H_ +#ifndef FLUTTER_LIB_UI_PAINTING_DISPLAY_LIST_DEFERRED_IMAGE_GPU_SKIA_H_ +#define FLUTTER_LIB_UI_PAINTING_DISPLAY_LIST_DEFERRED_IMAGE_GPU_SKIA_H_ #include #include @@ -20,16 +20,16 @@ namespace flutter { -class DlDeferredImageGPU final : public DlImage { +class DlDeferredImageGPUSkia final : public DlImage { public: - static sk_sp Make( + static sk_sp Make( const SkImageInfo& image_info, sk_sp display_list, fml::WeakPtr snapshot_delegate, fml::RefPtr raster_task_runner, fml::RefPtr unref_queue); - static sk_sp MakeFromLayerTree( + static sk_sp MakeFromLayerTree( const SkImageInfo& image_info, std::shared_ptr layer_tree, fml::WeakPtr snapshot_delegate, @@ -37,7 +37,7 @@ class DlDeferredImageGPU final : public DlImage { fml::RefPtr unref_queue); // |DlImage| - ~DlDeferredImageGPU() override; + ~DlDeferredImageGPUSkia() override; // |DlImage| // This method is only safe to call from the raster thread. @@ -135,12 +135,12 @@ class DlDeferredImageGPU final : public DlImage { fml::RefPtr raster_task_runner_; - DlDeferredImageGPU(std::shared_ptr image_wrapper, - fml::RefPtr raster_task_runner); + DlDeferredImageGPUSkia(std::shared_ptr image_wrapper, + fml::RefPtr raster_task_runner); - FML_DISALLOW_COPY_AND_ASSIGN(DlDeferredImageGPU); + FML_DISALLOW_COPY_AND_ASSIGN(DlDeferredImageGPUSkia); }; } // namespace flutter -#endif // FLUTTER_LIB_UI_PAINTING_DISPLAY_LIST_DEFERRED_IMAGE_GPU_H_ +#endif // FLUTTER_LIB_UI_PAINTING_DISPLAY_LIST_DEFERRED_IMAGE_GPU_SKIA_H_ diff --git a/engine/src/flutter/lib/ui/painting/picture.cc b/engine/src/flutter/lib/ui/painting/picture.cc index a8cb2a7e348..49622ce7d2a 100644 --- a/engine/src/flutter/lib/ui/painting/picture.cc +++ b/engine/src/flutter/lib/ui/painting/picture.cc @@ -8,8 +8,11 @@ #include "flutter/fml/make_copyable.h" #include "flutter/lib/ui/painting/canvas.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/ui_dart_state.h" +#if IMPELLER_SUPPORTS_RENDERING +#include "flutter/lib/ui/painting/display_list_deferred_image_gpu_impeller.h" +#endif // IMPELLER_SUPPORTS_RENDERING #include "third_party/tonic/converter/dart_converter.h" #include "third_party/tonic/dart_args.h" #include "third_party/tonic/dart_binding_macros.h" @@ -53,6 +56,29 @@ void Picture::toImageSync(uint32_t width, raw_image_handle); } +static sk_sp CreateDeferredImage( + bool impeller, + sk_sp display_list, + uint32_t width, + uint32_t height, + fml::WeakPtr snapshot_delegate, + fml::RefPtr raster_task_runner, + fml::RefPtr unref_queue) { +#if IMPELLER_SUPPORTS_RENDERING + if (impeller) { + return DlDeferredImageGPUImpeller::Make( + std::move(display_list), 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::Make( + image_info, std::move(display_list), std::move(snapshot_delegate), + std::move(raster_task_runner), std::move(unref_queue)); +} + // static void Picture::RasterizeToImageSync(sk_sp display_list, uint32_t width, @@ -67,11 +93,10 @@ void Picture::RasterizeToImageSync(sk_sp display_list, 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::Make( - image_info, std::move(display_list), std::move(snapshot_delegate), - std::move(raster_task_runner), std::move(unref_queue)); + auto dl_image = CreateDeferredImage( + dart_state->IsImpellerEnabled(), display_list, 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); } diff --git a/engine/src/flutter/lib/ui/snapshot_delegate.h b/engine/src/flutter/lib/ui/snapshot_delegate.h index 07b0c7cf6f4..6f9fc113a33 100644 --- a/engine/src/flutter/lib/ui/snapshot_delegate.h +++ b/engine/src/flutter/lib/ui/snapshot_delegate.h @@ -9,6 +9,7 @@ #include "flutter/common/graphics/texture.h" #include "flutter/display_list/display_list.h" +#include "flutter/flow/skia_gpu_object.h" #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkPicture.h" #include "third_party/skia/include/core/SkPromiseImageTexture.h" @@ -21,6 +22,9 @@ class DlImage; class SnapshotDelegate { public: + //---------------------------------------------------------------------------- + /// @brief A data structure used by the Skia implementation of deferred + /// GPU based images. struct GpuImageResult { GpuImageResult(const GrBackendTexture& p_texture, sk_sp p_context, @@ -44,6 +48,14 @@ class SnapshotDelegate { const std::string error; }; + //---------------------------------------------------------------------------- + /// @brief Attempts to create a GrBackendTexture for the specified + /// DisplayList. May result in a raster bitmap if no GPU context + /// is available. + virtual std::unique_ptr MakeSkiaGpuImage( + sk_sp display_list, + const SkImageInfo& image_info) = 0; + //---------------------------------------------------------------------------- /// @brief Gets the registry of external textures currently in use by the /// rasterizer. These textures may be updated at a cadence @@ -57,10 +69,6 @@ class SnapshotDelegate { virtual GrDirectContext* GetGrContext() = 0; - virtual std::unique_ptr MakeGpuImage( - sk_sp display_list, - const SkImageInfo& image_info) = 0; - virtual sk_sp MakeRasterSnapshot(sk_sp display_list, SkISize picture_size) = 0; diff --git a/engine/src/flutter/lib/ui/ui_dart_state.cc b/engine/src/flutter/lib/ui/ui_dart_state.cc index 208951c3238..133ea553952 100644 --- a/engine/src/flutter/lib/ui/ui_dart_state.cc +++ b/engine/src/flutter/lib/ui/ui_dart_state.cc @@ -36,7 +36,8 @@ UIDartState::Context::Context( fml::WeakPtr image_generator_registry, std::string advisory_script_uri, std::string advisory_script_entrypoint, - std::shared_ptr volatile_path_tracker) + std::shared_ptr volatile_path_tracker, + bool enable_impeller) : task_runners(task_runners), snapshot_delegate(snapshot_delegate), io_manager(io_manager), @@ -45,7 +46,8 @@ UIDartState::Context::Context( image_generator_registry(image_generator_registry), advisory_script_uri(advisory_script_uri), advisory_script_entrypoint(advisory_script_entrypoint), - volatile_path_tracker(volatile_path_tracker) {} + volatile_path_tracker(volatile_path_tracker), + enable_impeller(enable_impeller) {} UIDartState::UIDartState( TaskObserverAdd add_callback, @@ -77,6 +79,10 @@ const std::string& UIDartState::GetAdvisoryScriptURI() const { return context_.advisory_script_uri; } +bool UIDartState::IsImpellerEnabled() const { + return context_.enable_impeller; +} + void UIDartState::DidSetIsolate() { main_port_ = Dart_GetMainPortId(); std::ostringstream debug_name; diff --git a/engine/src/flutter/lib/ui/ui_dart_state.h b/engine/src/flutter/lib/ui/ui_dart_state.h index 95ccd9b3e43..e0deb57cbd5 100644 --- a/engine/src/flutter/lib/ui/ui_dart_state.h +++ b/engine/src/flutter/lib/ui/ui_dart_state.h @@ -53,7 +53,8 @@ class UIDartState : public tonic::DartState { fml::WeakPtr image_generator_registry, std::string advisory_script_uri, std::string advisory_script_entrypoint, - std::shared_ptr volatile_path_tracker); + std::shared_ptr volatile_path_tracker, + bool enable_impeller); /// The task runners used by the shell hosting this runtime controller. This /// may be used by the isolate to scheduled asynchronous texture uploads or @@ -91,6 +92,9 @@ class UIDartState : public tonic::DartState { /// Cache for tracking path volatility. std::shared_ptr volatile_path_tracker; + + /// Whether Impeller is enabled or not. + bool enable_impeller = false; }; Dart_Port main_port() const { return main_port_; } @@ -163,6 +167,9 @@ class UIDartState : public tonic::DartState { /// Returns `0` if called from a non-root isolate. int64_t GetRootIsolateToken() const; + /// Whether Impeller is enabled for this application. + bool IsImpellerEnabled() const; + protected: UIDartState(TaskObserverAdd add_callback, TaskObserverRemove remove_callback, diff --git a/engine/src/flutter/runtime/runtime_controller.cc b/engine/src/flutter/runtime/runtime_controller.cc index 292b32ade23..3522901705e 100644 --- a/engine/src/flutter/runtime/runtime_controller.cc +++ b/engine/src/flutter/runtime/runtime_controller.cc @@ -54,12 +54,16 @@ std::unique_ptr RuntimeController::Spawn( fml::WeakPtr image_decoder, fml::WeakPtr image_generator_registry, fml::WeakPtr snapshot_delegate) const { - UIDartState::Context spawned_context{ - context_.task_runners, std::move(snapshot_delegate), - std::move(io_manager), context_.unref_queue, - std::move(image_decoder), std::move(image_generator_registry), - advisory_script_uri, advisory_script_entrypoint, - context_.volatile_path_tracker}; + UIDartState::Context spawned_context{context_.task_runners, + std::move(snapshot_delegate), + std::move(io_manager), + context_.unref_queue, + std::move(image_decoder), + std::move(image_generator_registry), + advisory_script_uri, + advisory_script_entrypoint, + context_.volatile_path_tracker, + context_.enable_impeller}; auto result = std::make_unique(p_client, // vm_, // diff --git a/engine/src/flutter/shell/common/engine.cc b/engine/src/flutter/shell/common/engine.cc index 3eeea5ccd0a..1a07631ccab 100644 --- a/engine/src/flutter/shell/common/engine.cc +++ b/engine/src/flutter/shell/common/engine.cc @@ -100,6 +100,7 @@ Engine::Engine(Delegate& delegate, settings_.advisory_script_uri, // advisory script uri settings_.advisory_script_entrypoint, // advisory script entrypoint std::move(volatile_path_tracker), // volatile path tracker + settings_.enable_impeller, // enable impeller }); } diff --git a/engine/src/flutter/shell/common/rasterizer.cc b/engine/src/flutter/shell/common/rasterizer.cc index e35c953b677..9019e08e6ce 100644 --- a/engine/src/flutter/shell/common/rasterizer.cc +++ b/engine/src/flutter/shell/common/rasterizer.cc @@ -281,7 +281,7 @@ std::unique_ptr MakeBitmapImage( } } // namespace -std::unique_ptr Rasterizer::MakeGpuImage( +std::unique_ptr Rasterizer::MakeSkiaGpuImage( sk_sp display_list, const SkImageInfo& image_info) { TRACE_EVENT0("flutter", "Rasterizer::MakeGpuImage"); @@ -536,8 +536,8 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe( frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); std::unique_ptr damage; - // when leaf layer tracing is enabled we wish to repaint the whole frame for - // accurate performance metrics. + // when leaf layer tracing is enabled we wish to repaint the whole frame + // for accurate performance metrics. if (frame->framebuffer_info().supports_partial_repaint && !layer_tree.is_leaf_layer_tracing_enabled()) { // Disable partial repaint if external_view_embedder_ SubmitFrame is @@ -576,9 +576,9 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe( SurfaceFrame::SubmitInfo submit_info; // TODO (https://github.com/flutter/flutter/issues/105596): this can be in - // the past and might need to get snapped to future as this frame could have - // been resubmitted. `presentation_time` on `submit_info` is not set in this - // case. + // the past and might need to get snapped to future as this frame could + // have been resubmitted. `presentation_time` on `submit_info` is not set + // in this case. const auto presentation_time = frame_timings_recorder.GetVsyncTargetTime(); if (presentation_time > fml::TimePoint::Now()) { submit_info.presentation_time = presentation_time; @@ -649,8 +649,8 @@ sk_sp Rasterizer::ScreenshotLayerTreeAsImage( flutter::CompositorContext& compositor_context, GrDirectContext* surface_context, bool compressed) { - // Attempt to create a snapshot surface depending on whether we have access to - // a valid GPU rendering context. + // Attempt to create a snapshot surface depending on whether we have access + // to a valid GPU rendering context. std::unique_ptr snapshot_surface = std::make_unique(surface_context, tree->frame_size()); @@ -662,15 +662,15 @@ sk_sp Rasterizer::ScreenshotLayerTreeAsImage( // Draw the current layer tree into the snapshot surface. auto* canvas = snapshot_surface->GetCanvas(); - // There is no root surface transformation for the screenshot layer. Reset the - // matrix to identity. + // There is no root surface transformation for the screenshot layer. Reset + // the matrix to identity. SkMatrix root_surface_transformation; root_surface_transformation.reset(); // snapshot_surface->makeImageSnapshot needs the GL context to be set if the - // render context is GL. frame->Raster() pops the gl context in platforms that - // gl context switching are used. (For example, older iOS that uses GL) We - // reset the GL context using the context switch. + // render context is GL. frame->Raster() pops the gl context in platforms + // that gl context switching are used. (For example, older iOS that uses GL) + // We reset the GL context using the context switch. auto context_switch = surface_->MakeRenderContextCurrent(); if (!context_switch->GetResult()) { FML_LOG(ERROR) << "Screenshot: unable to make image screenshot"; diff --git a/engine/src/flutter/shell/common/rasterizer.h b/engine/src/flutter/shell/common/rasterizer.h index 9a3eb94486c..0c28af9c758 100644 --- a/engine/src/flutter/shell/common/rasterizer.h +++ b/engine/src/flutter/shell/common/rasterizer.h @@ -106,11 +106,11 @@ class Rasterizer final : public SnapshotDelegate, }; //---------------------------------------------------------------------------- - /// @brief How to handle calls to MakeGpuImage. + /// @brief How to handle calls to MakeSkiaGpuImage. enum class MakeGpuImageBehavior { - /// MakeGpuImage returns a GPU resident image, if possible. + /// MakeSkiaGpuImage returns a GPU resident image, if possible. kGpu, - /// MakeGpuImage returns a checkerboard bitmap. This is useful in test + /// MakeSkiaGpuImage returns a checkerboard bitmap. This is useful in test /// contexts where no GPU surface is available. kBitmap, }; @@ -123,7 +123,7 @@ class Rasterizer final : public SnapshotDelegate, /// /// @param[in] delegate The rasterizer delegate. /// @param[in] gpu_image_behavior How to handle calls to - /// MakeGpuImage. + /// MakeSkiaGpuImage. /// explicit Rasterizer( Delegate& delegate, @@ -470,7 +470,7 @@ class Rasterizer final : public SnapshotDelegate, private: // |SnapshotDelegate| - std::unique_ptr MakeGpuImage( + std::unique_ptr MakeSkiaGpuImage( sk_sp display_list, const SkImageInfo& image_info) override;