From 4f1522ddbee1dd88cb4e05de7092bc3da0f0a44a Mon Sep 17 00:00:00 2001 From: ColdPaleLight Date: Tue, 29 Nov 2022 13:33:20 +0800 Subject: [PATCH 1/2] [Impeller] Implement 'ui.Image.toByteData()' --- ci/licenses_golden/licenses_flutter | 4 + .../display_list_image_impeller.cc | 11 +- .../display_list_image_impeller.h | 11 +- lib/ui/BUILD.gn | 4 + ...display_list_deferred_image_gpu_impeller.h | 5 + lib/ui/painting/image_encoding.cc | 111 +++--------- lib/ui/painting/image_encoding_impeller.cc | 160 ++++++++++++++++++ lib/ui/painting/image_encoding_impeller.h | 28 +++ lib/ui/painting/image_encoding_skia.cc | 102 +++++++++++ lib/ui/painting/image_encoding_skia.h | 26 +++ shell/common/snapshot_controller_impeller.cc | 3 +- 11 files changed, 373 insertions(+), 92 deletions(-) create mode 100644 lib/ui/painting/image_encoding_impeller.cc create mode 100644 lib/ui/painting/image_encoding_impeller.h create mode 100644 lib/ui/painting/image_encoding_skia.cc create mode 100644 lib/ui/painting/image_encoding_skia.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index daa6e2755f882..8d268e24577fa 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1713,7 +1713,11 @@ FILE: ../../../flutter/lib/ui/painting/image_descriptor.h FILE: ../../../flutter/lib/ui/painting/image_dispose_unittests.cc FILE: ../../../flutter/lib/ui/painting/image_encoding.cc FILE: ../../../flutter/lib/ui/painting/image_encoding.h +FILE: ../../../flutter/lib/ui/painting/image_encoding_impeller.cc +FILE: ../../../flutter/lib/ui/painting/image_encoding_impeller.h FILE: ../../../flutter/lib/ui/painting/image_encoding_impl.h +FILE: ../../../flutter/lib/ui/painting/image_encoding_skia.cc +FILE: ../../../flutter/lib/ui/painting/image_encoding_skia.h FILE: ../../../flutter/lib/ui/painting/image_encoding_unittests.cc FILE: ../../../flutter/lib/ui/painting/image_filter.cc FILE: ../../../flutter/lib/ui/painting/image_filter.h diff --git a/impeller/display_list/display_list_image_impeller.cc b/impeller/display_list/display_list_image_impeller.cc index ae71d94132578..7650a41ff364c 100644 --- a/impeller/display_list/display_list_image_impeller.cc +++ b/impeller/display_list/display_list_image_impeller.cc @@ -9,11 +9,13 @@ namespace impeller { -sk_sp DlImageImpeller::Make(std::shared_ptr texture) { +sk_sp DlImageImpeller::Make(std::shared_ptr texture, + OwningContext owning_context) { if (!texture) { return nullptr; } - return sk_sp(new DlImageImpeller(std::move(texture))); + return sk_sp( + new DlImageImpeller(std::move(texture), owning_context)); } sk_sp DlImageImpeller::MakeFromYUVTextures( @@ -33,8 +35,9 @@ sk_sp DlImageImpeller::MakeFromYUVTextures( return impeller::DlImageImpeller::Make(snapshot->texture); } -DlImageImpeller::DlImageImpeller(std::shared_ptr texture) - : texture_(std::move(texture)) {} +DlImageImpeller::DlImageImpeller(std::shared_ptr texture, + OwningContext owning_context) + : texture_(std::move(texture)), owning_context_(owning_context) {} // |DlImage| DlImageImpeller::~DlImageImpeller() = default; diff --git a/impeller/display_list/display_list_image_impeller.h b/impeller/display_list/display_list_image_impeller.h index 65b9c2892bc2a..88484a0fc46fa 100644 --- a/impeller/display_list/display_list_image_impeller.h +++ b/impeller/display_list/display_list_image_impeller.h @@ -14,7 +14,9 @@ class AiksContext; class DlImageImpeller final : public flutter::DlImage { public: - static sk_sp Make(std::shared_ptr texture); + static sk_sp Make( + std::shared_ptr texture, + OwningContext owning_context = OwningContext::kIO); static sk_sp MakeFromYUVTextures( AiksContext* aiks_context, @@ -43,10 +45,15 @@ class DlImageImpeller final : public flutter::DlImage { // |DlImage| size_t GetApproximateByteSize() const override; + // |DlImage| + OwningContext owning_context() const override { return owning_context_; } + private: std::shared_ptr texture_; + OwningContext owning_context_; - explicit DlImageImpeller(std::shared_ptr texture); + explicit DlImageImpeller(std::shared_ptr texture, + OwningContext owning_context = OwningContext::kIO); FML_DISALLOW_COPY_AND_ASSIGN(DlImageImpeller); }; diff --git a/lib/ui/BUILD.gn b/lib/ui/BUILD.gn index a63414838b5ed..fff9b1cf7bc4a 100644 --- a/lib/ui/BUILD.gn +++ b/lib/ui/BUILD.gn @@ -53,6 +53,8 @@ source_set("ui") { "painting/image_encoding.cc", "painting/image_encoding.h", "painting/image_encoding_impl.h", + "painting/image_encoding_skia.cc", + "painting/image_encoding_skia.h", "painting/image_filter.cc", "painting/image_filter.h", "painting/image_generator.cc", @@ -167,6 +169,8 @@ source_set("ui") { "painting/display_list_deferred_image_gpu_impeller.h", "painting/image_decoder_impeller.cc", "painting/image_decoder_impeller.h", + "painting/image_encoding_impeller.cc", + "painting/image_encoding_impeller.h", ] deps += [ "//flutter/impeller" ] diff --git a/lib/ui/painting/display_list_deferred_image_gpu_impeller.h b/lib/ui/painting/display_list_deferred_image_gpu_impeller.h index 7fa57ecb163a6..84d6e9aec33a2 100644 --- a/lib/ui/painting/display_list_deferred_image_gpu_impeller.h +++ b/lib/ui/painting/display_list_deferred_image_gpu_impeller.h @@ -50,6 +50,11 @@ class DlDeferredImageGPUImpeller final : public DlImage { // |DlImage| size_t GetApproximateByteSize() const override; + // |DlImage| + OwningContext owning_context() const override { + return OwningContext::kRaster; + } + private: class ImageWrapper final : public std::enable_shared_from_this, public ContextListener { diff --git a/lib/ui/painting/image_encoding.cc b/lib/ui/painting/image_encoding.cc index 7f3e9d56c96d6..2e60d5f55f0e3 100644 --- a/lib/ui/painting/image_encoding.cc +++ b/lib/ui/painting/image_encoding.cc @@ -13,6 +13,10 @@ #include "flutter/fml/make_copyable.h" #include "flutter/fml/trace_event.h" #include "flutter/lib/ui/painting/image.h" +#if IMPELLER_SUPPORTS_RENDERING +#include "flutter/lib/ui/painting/image_encoding_impeller.h" +#endif // IMPELLER_SUPPORTS_RENDERING +#include "flutter/lib/ui/painting/image_encoding_skia.h" #include "third_party/skia/include/core/SkEncodedImageFormat.h" #include "third_party/tonic/dart_persistent_value.h" #include "third_party/tonic/logging/dart_invoke.h" @@ -22,6 +26,9 @@ using tonic::DartInvoke; using tonic::DartPersistentValue; using tonic::ToDart; +namespace impeller { +class Context; +} // namespace impeller namespace flutter { namespace { @@ -60,84 +67,6 @@ void InvokeDataCallback(std::unique_ptr callback, DartInvoke(callback->value(), {dart_data}); } -void ConvertImageToRaster( - const sk_sp& dl_image, - std::function)> encode_task, - const fml::RefPtr& raster_task_runner, - const fml::RefPtr& io_task_runner, - const fml::WeakPtr& resource_context, - const fml::TaskRunnerAffineWeakPtr& snapshot_delegate, - const std::shared_ptr& is_gpu_disabled_sync_switch) { - // If the owning_context is kRaster, we can't access it on this task runner. - if (dl_image->owning_context() != DlImage::OwningContext::kRaster) { - auto image = dl_image->skia_image(); - - // Check validity of the image. - if (image == nullptr) { - FML_LOG(ERROR) << "Image was null."; - encode_task(nullptr); - return; - } - - auto dimensions = image->dimensions(); - - if (dimensions.isEmpty()) { - FML_LOG(ERROR) << "Image dimensions were empty."; - encode_task(nullptr); - return; - } - - SkPixmap pixmap; - if (image->peekPixels(&pixmap)) { - // This is already a raster image. - encode_task(image); - return; - } - - if (sk_sp raster_image = image->makeRasterImage()) { - // The image can be converted to a raster image. - encode_task(raster_image); - return; - } - } - - // Cross-context images do not support makeRasterImage. Convert these images - // by drawing them into a surface. This must be done on the raster thread - // to prevent concurrent usage of the image on both the IO and raster threads. - raster_task_runner->PostTask([dl_image, encode_task = std::move(encode_task), - resource_context, snapshot_delegate, - io_task_runner, is_gpu_disabled_sync_switch, - raster_task_runner]() { - auto image = dl_image->skia_image(); - if (!image || !snapshot_delegate) { - io_task_runner->PostTask( - [encode_task = encode_task]() mutable { encode_task(nullptr); }); - return; - } - - sk_sp raster_image = - snapshot_delegate->ConvertToRasterImage(image); - - io_task_runner->PostTask([image, encode_task = encode_task, - raster_image = std::move(raster_image), - resource_context, is_gpu_disabled_sync_switch, - owning_context = dl_image->owning_context(), - raster_task_runner]() mutable { - if (!raster_image) { - // The rasterizer was unable to render the cross-context image - // (presumably because it does not have a GrContext). In that case, - // convert the image on the IO thread using the resource context. - raster_image = ConvertToRasterUsingResourceContext( - image, resource_context, is_gpu_disabled_sync_switch); - } - encode_task(raster_image); - if (owning_context == DlImage::OwningContext::kRaster) { - raster_task_runner->PostTask([image = std::move(image)]() {}); - } - }); - }); -} - sk_sp CopyImageByteData(const sk_sp& raster_image, SkColorType color_type, SkAlphaType alpha_type) { @@ -221,7 +150,9 @@ void EncodeImageAndInvokeDataCallback( const fml::RefPtr& io_task_runner, const fml::WeakPtr& resource_context, const fml::TaskRunnerAffineWeakPtr& snapshot_delegate, - const std::shared_ptr& is_gpu_disabled_sync_switch) { + const std::shared_ptr& is_gpu_disabled_sync_switch, + const std::shared_ptr& impeller_context, + bool is_impeller_enabled) { auto callback_task = fml::MakeCopyable( [callback = std::move(callback)](sk_sp encoded) mutable { InvokeDataCallback(std::move(callback), std::move(encoded)); @@ -239,9 +170,17 @@ void EncodeImageAndInvokeDataCallback( }; FML_DCHECK(image); - ConvertImageToRaster(image, encode_task, raster_task_runner, io_task_runner, - resource_context, snapshot_delegate, - is_gpu_disabled_sync_switch); +#if IMPELLER_SUPPORTS_RENDERING + if (is_impeller_enabled) { + ConvertImageToRasterImpeller(image, encode_task, raster_task_runner, + io_task_runner, is_gpu_disabled_sync_switch, + impeller_context); + return; + } +#endif // IMPELLER_SUPPORTS_RENDERING + ConvertImageToRasterSkia(image, encode_task, raster_task_runner, + io_task_runner, resource_context, snapshot_delegate, + is_gpu_disabled_sync_switch); } } // namespace @@ -272,13 +211,15 @@ Dart_Handle EncodeImage(CanvasImage* canvas_image, raster_task_runner = task_runners.GetRasterTaskRunner(), io_task_runner = task_runners.GetIOTaskRunner(), io_manager = UIDartState::Current()->GetIOManager(), - snapshot_delegate = - UIDartState::Current()->GetSnapshotDelegate()]() mutable { + snapshot_delegate = UIDartState::Current()->GetSnapshotDelegate(), + is_impeller_enabled = + UIDartState::Current()->IsImpellerEnabled()]() mutable { EncodeImageAndInvokeDataCallback( image, std::move(callback), image_format, ui_task_runner, raster_task_runner, io_task_runner, io_manager->GetResourceContext(), snapshot_delegate, - io_manager->GetIsGpuDisabledSyncSwitch()); + io_manager->GetIsGpuDisabledSyncSwitch(), + io_manager->GetImpellerContext(), is_impeller_enabled); })); return Dart_Null(); diff --git a/lib/ui/painting/image_encoding_impeller.cc b/lib/ui/painting/image_encoding_impeller.cc new file mode 100644 index 0000000000000..bb4181670842e --- /dev/null +++ b/lib/ui/painting/image_encoding_impeller.cc @@ -0,0 +1,160 @@ +// 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/image.h" +#include "impeller/renderer/command_buffer.h" +#include "impeller/renderer/context.h" +#include "impeller/renderer/device_buffer.h" +#include "impeller/renderer/formats.h" + +namespace flutter { +namespace { + +std::optional ToSkColorType(impeller::PixelFormat format) { + switch (format) { + case impeller::PixelFormat::kR8G8B8A8UNormInt: + return SkColorType::kRGBA_8888_SkColorType; + case impeller::PixelFormat::kB8G8R8A8UNormInt: + return SkColorType::kBGRA_8888_SkColorType; + break; + default: + return std::nullopt; + break; + } +} + +sk_sp ConvertBufferToSkImage( + const std::shared_ptr& buffer, + impeller::PixelFormat format, + SkISize dimensions) { + auto buffer_view = buffer->AsBufferView(); + + auto color_type = ToSkColorType(format); + if (!color_type.has_value()) { + FML_LOG(ERROR) << "Failed to get color type from pixel format."; + } + SkImageInfo image_info = SkImageInfo::Make(dimensions, color_type.value(), + SkAlphaType::kPremul_SkAlphaType); + + SkBitmap bitmap; + auto func = [](void* addr, void* context) { + auto buffer = + static_cast*>(context); + buffer->reset(); + delete buffer; + }; + auto bytes_per_pixel = impeller::BytesPerPixelForPixelFormat(format); + bitmap.installPixels(image_info, buffer_view.contents, + dimensions.width() * bytes_per_pixel, func, + new std::shared_ptr(buffer)); + bitmap.setImmutable(); + + sk_sp raster_image = SkImage::MakeFromBitmap(bitmap); + return raster_image; +} + +void ConvertDlImageImpellerToSkImage( + const sk_sp& dl_image, + std::function)> encode_task, + const std::shared_ptr& impeller_context) { + auto texture = dl_image->impeller_texture(); + + if (impeller_context == nullptr) { + FML_LOG(ERROR) << "Impeller context was null."; + encode_task(nullptr); + return; + } + + if (texture == nullptr) { + FML_LOG(ERROR) << "Image was null."; + encode_task(nullptr); + return; + } + + auto dimensions = dl_image->dimensions(); + auto format = texture->GetTextureDescriptor().format; + + if (dimensions.isEmpty()) { + FML_LOG(ERROR) << "Image dimensions were empty."; + encode_task(nullptr); + return; + } + + impeller::DeviceBufferDescriptor buffer_desc; + buffer_desc.storage_mode = impeller::StorageMode::kHostVisible; + buffer_desc.size = + texture->GetTextureDescriptor().GetByteSizeOfBaseMipLevel(); + auto buffer = + impeller_context->GetResourceAllocator()->CreateBuffer(buffer_desc); + auto command_buffer = impeller_context->CreateCommandBuffer(); + command_buffer->SetLabel("BlitTextureToBuffer Command Buffer"); + auto pass = command_buffer->CreateBlitPass(); + pass->SetLabel("BlitTextureToBuffer Blit Pass"); + pass->AddCopy(texture, buffer); + pass->EncodeCommands(impeller_context->GetResourceAllocator()); + auto completion = [buffer, format, dimensions, + encode_task = std::move(encode_task)]( + impeller::CommandBuffer::Status status) { + if (status != impeller::CommandBuffer::Status::kCompleted) { + encode_task(nullptr); + return; + } + auto sk_image = ConvertBufferToSkImage(buffer, format, dimensions); + encode_task(sk_image); + }; + + if (!command_buffer->SubmitCommands()) { + FML_LOG(ERROR) << "Failed to submit commands."; + } +} + +void DoConvertImageToRasterImpeller( + const sk_sp& dl_image, + std::function)> encode_task, + const std::shared_ptr& is_gpu_disabled_sync_switch, + const std::shared_ptr& impeller_context) { + is_gpu_disabled_sync_switch->Execute( + fml::SyncSwitch::Handlers() + .SetIfTrue([&encode_task] { encode_task(nullptr); }) + .SetIfFalse([&dl_image, &encode_task, &impeller_context] { + ConvertDlImageImpellerToSkImage(dl_image, std::move(encode_task), + impeller_context); + })); +} + +} // namespace + +void ConvertImageToRasterImpeller( + const sk_sp& dl_image, + std::function)> encode_task, + const fml::RefPtr& raster_task_runner, + const fml::RefPtr& io_task_runner, + const std::shared_ptr& is_gpu_disabled_sync_switch, + const std::shared_ptr& impeller_context) { + auto original_encode_task = std::move(encode_task); + encode_task = [original_encode_task = std::move(original_encode_task), + io_task_runner](sk_sp image) mutable { + fml::TaskRunner::RunNowOrPostTask( + io_task_runner, + [original_encode_task = std::move(original_encode_task), + image = std::move(image)]() { original_encode_task(image); }); + }; + + if (dl_image->owning_context() != DlImage::OwningContext::kRaster) { + DoConvertImageToRasterImpeller(dl_image, std::move(encode_task), + is_gpu_disabled_sync_switch, + impeller_context); + return; + } + + raster_task_runner->PostTask([dl_image, encode_task = std::move(encode_task), + io_task_runner, is_gpu_disabled_sync_switch, + impeller_context]() mutable { + DoConvertImageToRasterImpeller(dl_image, std::move(encode_task), + is_gpu_disabled_sync_switch, + impeller_context); + }); +} + +} // namespace flutter diff --git a/lib/ui/painting/image_encoding_impeller.h b/lib/ui/painting/image_encoding_impeller.h new file mode 100644 index 0000000000000..459ecf50909c4 --- /dev/null +++ b/lib/ui/painting/image_encoding_impeller.h @@ -0,0 +1,28 @@ +// 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_PAINTING_IMAGE_ENCODING_IMPELLER_H_ +#define FLUTTER_LIB_UI_PAINTING_IMAGE_ENCODING_IMPELLER_H_ + +#include "flutter/common/task_runners.h" +#include "flutter/display_list/display_list_image.h" +#include "flutter/fml/synchronization/sync_switch.h" + +namespace impeller { +class Context; +} // namespace impeller + +namespace flutter { + +void ConvertImageToRasterImpeller( + const sk_sp& dl_image, + std::function)> encode_task, + const fml::RefPtr& raster_task_runner, + const fml::RefPtr& io_task_runner, + const std::shared_ptr& is_gpu_disabled_sync_switch, + const std::shared_ptr& impeller_context); + +} // namespace flutter + +#endif // FLUTTER_LIB_UI_PAINTING_IMAGE_ENCODING_IMPELLER_H_ diff --git a/lib/ui/painting/image_encoding_skia.cc b/lib/ui/painting/image_encoding_skia.cc new file mode 100644 index 0000000000000..7996c2b20bbac --- /dev/null +++ b/lib/ui/painting/image_encoding_skia.cc @@ -0,0 +1,102 @@ +// 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/image_encoding.h" +#include "flutter/lib/ui/painting/image_encoding_impl.h" + +#include "flutter/lib/ui/painting/image.h" + +namespace flutter { + +void ConvertImageToRasterSkia( + const sk_sp& dl_image, + std::function)> encode_task, + const fml::RefPtr& raster_task_runner, + const fml::RefPtr& io_task_runner, + const fml::WeakPtr& resource_context, + const fml::TaskRunnerAffineWeakPtr& snapshot_delegate, + const std::shared_ptr& is_gpu_disabled_sync_switch) { + // If the owning_context is kRaster, we can't access it on this task runner. + if (dl_image->owning_context() != DlImage::OwningContext::kRaster) { + auto image = dl_image->skia_image(); + + // Check validity of the image. + if (image == nullptr) { + FML_LOG(ERROR) << "Image was null."; + encode_task(nullptr); + return; + } + + auto dimensions = image->dimensions(); + + if (dimensions.isEmpty()) { + FML_LOG(ERROR) << "Image dimensions were empty."; + encode_task(nullptr); + return; + } + + SkPixmap pixmap; + if (image->peekPixels(&pixmap)) { + // This is already a raster image. + encode_task(image); + return; + } + + if (sk_sp raster_image = image->makeRasterImage()) { + // The image can be converted to a raster image. + encode_task(raster_image); + return; + } + } + + if (!raster_task_runner) { + FML_LOG(ERROR) << "Raster task runner was null."; + encode_task(nullptr); + return; + } + + if (!io_task_runner) { + FML_LOG(ERROR) << "IO task runner was null."; + encode_task(nullptr); + return; + } + + // Cross-context images do not support makeRasterImage. Convert these images + // by drawing them into a surface. This must be done on the raster thread + // to prevent concurrent usage of the image on both the IO and raster threads. + raster_task_runner->PostTask([dl_image, encode_task = std::move(encode_task), + resource_context, snapshot_delegate, + io_task_runner, is_gpu_disabled_sync_switch, + raster_task_runner]() { + auto image = dl_image->skia_image(); + if (!image || !snapshot_delegate) { + io_task_runner->PostTask( + [encode_task = encode_task]() mutable { encode_task(nullptr); }); + return; + } + + sk_sp raster_image = + snapshot_delegate->ConvertToRasterImage(image); + + io_task_runner->PostTask([image, encode_task = encode_task, + raster_image = std::move(raster_image), + resource_context, is_gpu_disabled_sync_switch, + owning_context = dl_image->owning_context(), + raster_task_runner]() mutable { + if (!raster_image) { + // The rasterizer was unable to render the cross-context image + // (presumably because it does not have a GrContext). In that case, + // convert the image on the IO thread using the resource context. + raster_image = ConvertToRasterUsingResourceContext( + image, resource_context, is_gpu_disabled_sync_switch); + } + encode_task(raster_image); + if (owning_context == DlImage::OwningContext::kRaster) { + raster_task_runner->PostTask([image = std::move(image)]() {}); + } + }); + }); +} + +} // namespace flutter diff --git a/lib/ui/painting/image_encoding_skia.h b/lib/ui/painting/image_encoding_skia.h new file mode 100644 index 0000000000000..071aadbeba7cd --- /dev/null +++ b/lib/ui/painting/image_encoding_skia.h @@ -0,0 +1,26 @@ +// 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_PAINTING_IMAGE_ENCODING_SKIA_H_ +#define FLUTTER_LIB_UI_PAINTING_IMAGE_ENCODING_SKIA_H_ + +#include "flutter/common/task_runners.h" +#include "flutter/display_list/display_list_image.h" +#include "flutter/fml/synchronization/sync_switch.h" +#include "flutter/lib/ui/snapshot_delegate.h" + +namespace flutter { + +void ConvertImageToRasterSkia( + const sk_sp& dl_image, + std::function)> encode_task, + const fml::RefPtr& raster_task_runner, + const fml::RefPtr& io_task_runner, + const fml::WeakPtr& resource_context, + const fml::TaskRunnerAffineWeakPtr& snapshot_delegate, + const std::shared_ptr& is_gpu_disabled_sync_switch); + +} // namespace flutter + +#endif // FLUTTER_LIB_UI_PAINTING_IMAGE_ENCODING_SKIA_H_ diff --git a/shell/common/snapshot_controller_impeller.cc b/shell/common/snapshot_controller_impeller.cc index 6e5d65b74769c..5e7317805812d 100644 --- a/shell/common/snapshot_controller_impeller.cc +++ b/shell/common/snapshot_controller_impeller.cc @@ -64,7 +64,8 @@ sk_sp SnapshotControllerImpeller::DoMakeRasterSnapshot( std::shared_ptr image = picture.ToImage(*context, render_target_size); if (image) { - return impeller::DlImageImpeller::Make(image->GetTexture()); + return impeller::DlImageImpeller::Make(image->GetTexture(), + DlImage::OwningContext::kRaster); } } From c7b40110b306083a4f3fee6cf51976b69a16a9a3 Mon Sep 17 00:00:00 2001 From: ColdPaleLight Date: Thu, 1 Dec 2022 11:43:18 +0800 Subject: [PATCH 2/2] Tweak code --- lib/ui/painting/image_encoding_impeller.cc | 24 ++++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/lib/ui/painting/image_encoding_impeller.cc b/lib/ui/painting/image_encoding_impeller.cc index bb4181670842e..bfb2365e428a4 100644 --- a/lib/ui/painting/image_encoding_impeller.cc +++ b/lib/ui/painting/image_encoding_impeller.cc @@ -26,15 +26,11 @@ std::optional ToSkColorType(impeller::PixelFormat format) { sk_sp ConvertBufferToSkImage( const std::shared_ptr& buffer, - impeller::PixelFormat format, + SkColorType color_type, SkISize dimensions) { auto buffer_view = buffer->AsBufferView(); - auto color_type = ToSkColorType(format); - if (!color_type.has_value()) { - FML_LOG(ERROR) << "Failed to get color type from pixel format."; - } - SkImageInfo image_info = SkImageInfo::Make(dimensions, color_type.value(), + SkImageInfo image_info = SkImageInfo::Make(dimensions, color_type, SkAlphaType::kPremul_SkAlphaType); SkBitmap bitmap; @@ -44,7 +40,7 @@ sk_sp ConvertBufferToSkImage( buffer->reset(); delete buffer; }; - auto bytes_per_pixel = impeller::BytesPerPixelForPixelFormat(format); + auto bytes_per_pixel = image_info.bytesPerPixel(); bitmap.installPixels(image_info, buffer_view.contents, dimensions.width() * bytes_per_pixel, func, new std::shared_ptr(buffer)); @@ -73,7 +69,7 @@ void ConvertDlImageImpellerToSkImage( } auto dimensions = dl_image->dimensions(); - auto format = texture->GetTextureDescriptor().format; + auto color_type = ToSkColorType(texture->GetTextureDescriptor().format); if (dimensions.isEmpty()) { FML_LOG(ERROR) << "Image dimensions were empty."; @@ -81,6 +77,12 @@ void ConvertDlImageImpellerToSkImage( return; } + if (!color_type.has_value()) { + FML_LOG(ERROR) << "Failed to get color type from pixel format."; + encode_task(nullptr); + return; + } + impeller::DeviceBufferDescriptor buffer_desc; buffer_desc.storage_mode = impeller::StorageMode::kHostVisible; buffer_desc.size = @@ -93,18 +95,18 @@ void ConvertDlImageImpellerToSkImage( pass->SetLabel("BlitTextureToBuffer Blit Pass"); pass->AddCopy(texture, buffer); pass->EncodeCommands(impeller_context->GetResourceAllocator()); - auto completion = [buffer, format, dimensions, + auto completion = [buffer, color_type = color_type.value(), dimensions, encode_task = std::move(encode_task)]( impeller::CommandBuffer::Status status) { if (status != impeller::CommandBuffer::Status::kCompleted) { encode_task(nullptr); return; } - auto sk_image = ConvertBufferToSkImage(buffer, format, dimensions); + auto sk_image = ConvertBufferToSkImage(buffer, color_type, dimensions); encode_task(sk_image); }; - if (!command_buffer->SubmitCommands()) { + if (!command_buffer->SubmitCommands(completion)) { FML_LOG(ERROR) << "Failed to submit commands."; } }