diff --git a/lib/ui/painting/image_decoder_impeller.cc b/lib/ui/painting/image_decoder_impeller.cc index 31a5ab0db815d..4130f37e75794 100644 --- a/lib/ui/painting/image_decoder_impeller.cc +++ b/lib/ui/painting/image_decoder_impeller.cc @@ -137,7 +137,7 @@ std::shared_ptr ImageDecoderImpeller::DecompressTexture( return scaled_bitmap; } -static sk_sp UploadTexture( +sk_sp ImageDecoderImpeller::UploadTexture( const std::shared_ptr& context, std::shared_ptr bitmap) { TRACE_EVENT0("impeller", __FUNCTION__); diff --git a/lib/ui/painting/image_decoder_impeller.h b/lib/ui/painting/image_decoder_impeller.h index 0d1afcf2a3dcc..fdaa0a600f006 100644 --- a/lib/ui/painting/image_decoder_impeller.h +++ b/lib/ui/painting/image_decoder_impeller.h @@ -37,6 +37,10 @@ class ImageDecoderImpeller final : public ImageDecoder { SkISize target_size, impeller::ISize max_texture_size); + static sk_sp UploadTexture( + const std::shared_ptr& context, + std::shared_ptr bitmap); + private: using FutureContext = std::shared_future>; FutureContext context_; diff --git a/lib/ui/painting/multi_frame_codec.cc b/lib/ui/painting/multi_frame_codec.cc index 986c2f5e6721f..a292025107150 100644 --- a/lib/ui/painting/multi_frame_codec.cc +++ b/lib/ui/painting/multi_frame_codec.cc @@ -8,6 +8,9 @@ #include "flutter/fml/make_copyable.h" #include "flutter/lib/ui/painting/image.h" +#if IMPELLER_SUPPORTS_RENDERING +#include "lib/ui/painting/image_decoder_impeller.h" +#endif // IMPELLER_SUPPORTS_RENDERING #include "third_party/dart/runtime/include/dart_api.h" #include "third_party/skia/include/core/SkPixelRef.h" #include "third_party/tonic/logging/dart_invoke.h" @@ -26,6 +29,7 @@ MultiFrameCodec::State::State(std::shared_ptr generator) ImageGenerator::kInfinitePlayCount ? -1 : generator_->GetPlayCount() - 1), + is_impeller_enabled_(UIDartState::Current()->IsImpellerEnabled()), nextFrameIndex_(0) {} static void InvokeNextFrameCallback( @@ -77,9 +81,11 @@ static bool CopyToBitmap(SkBitmap* dst, return true; } -sk_sp MultiFrameCodec::State::GetNextFrameImage( +sk_sp MultiFrameCodec::State::GetNextFrameImage( fml::WeakPtr resourceContext, - const std::shared_ptr& gpu_disable_sync_switch) { + const std::shared_ptr& gpu_disable_sync_switch, + std::shared_ptr impeller_context_, + fml::RefPtr unref_queue) { SkBitmap bitmap = SkBitmap(); SkImageInfo info = generator_->GetInfo().makeColorType(kN32_SkColorType); if (info.alphaType() == kUnpremul_SkAlphaType) { @@ -125,30 +131,45 @@ sk_sp MultiFrameCodec::State::GetNextFrameImage( lastRequiredFrame_ = std::make_unique(bitmap); lastRequiredFrameIndex_ = nextFrameIndex_; } - sk_sp result; +#if IMPELLER_SUPPORTS_RENDERING + if (is_impeller_enabled_) { + sk_sp result; + // impeller, transfer to DlImageImpeller + gpu_disable_sync_switch->Execute(fml::SyncSwitch::Handlers().SetIfFalse( + [&result, &bitmap, &impeller_context_] { + result = ImageDecoderImpeller::UploadTexture( + impeller_context_, std::make_shared(bitmap)); + })); + + return result; + } +#endif // IMPELLER_SUPPORTS_RENDERING + + sk_sp skImage; gpu_disable_sync_switch->Execute( fml::SyncSwitch::Handlers() - .SetIfTrue([&result, &bitmap] { + .SetIfTrue([&skImage, &bitmap] { // Defer decoding until time of draw later on the raster thread. Can // happen when GL operations are currently forbidden such as in the // background on iOS. - result = SkImage::MakeFromBitmap(bitmap); + skImage = SkImage::MakeFromBitmap(bitmap); }) - .SetIfFalse([&result, &resourceContext, &bitmap] { + .SetIfFalse([&skImage, &resourceContext, &bitmap] { if (resourceContext) { SkPixmap pixmap(bitmap.info(), bitmap.pixelRef()->pixels(), bitmap.pixelRef()->rowBytes()); - result = SkImage::MakeCrossContextFromPixmap( + skImage = SkImage::MakeCrossContextFromPixmap( resourceContext.get(), pixmap, true); } else { // Defer decoding until time of draw later on the raster thread. // Can happen when GL operations are currently forbidden such as // in the background on iOS. - result = SkImage::MakeFromBitmap(bitmap); + skImage = SkImage::MakeFromBitmap(bitmap); } })); - return result; + + return DlImageGPU::Make({skImage, std::move(unref_queue)}); } void MultiFrameCodec::State::GetNextFrameAndInvokeCallback( @@ -157,14 +178,16 @@ void MultiFrameCodec::State::GetNextFrameAndInvokeCallback( fml::WeakPtr resourceContext, fml::RefPtr unref_queue, const std::shared_ptr& gpu_disable_sync_switch, - size_t trace_id) { + size_t trace_id, + std::shared_ptr impeller_context) { fml::RefPtr image = nullptr; int duration = 0; - sk_sp skImage = - GetNextFrameImage(std::move(resourceContext), gpu_disable_sync_switch); - if (skImage) { + sk_sp dlImage = + GetNextFrameImage(std::move(resourceContext), gpu_disable_sync_switch, + impeller_context, unref_queue); + if (dlImage) { image = CanvasImage::Create(); - image->set_image(DlImageGPU::Make({skImage, std::move(unref_queue)})); + image->set_image(dlImage); ImageGenerator::FrameInfo frameInfo = generator_->GetFrameInfo(nextFrameIndex_); duration = frameInfo.duration; @@ -218,7 +241,8 @@ Dart_Handle MultiFrameCodec::getNextFrame(Dart_Handle callback_handle) { state->GetNextFrameAndInvokeCallback( std::move(callback), ui_task_runner, io_manager->GetResourceContext(), io_manager->GetSkiaUnrefQueue(), - io_manager->GetIsGpuDisabledSyncSwitch(), trace_id); + io_manager->GetIsGpuDisabledSyncSwitch(), trace_id, + io_manager->GetImpellerContext()); })); return Dart_Null(); diff --git a/lib/ui/painting/multi_frame_codec.h b/lib/ui/painting/multi_frame_codec.h index 3ccf8c7699ffc..3cb42b0706bc4 100644 --- a/lib/ui/painting/multi_frame_codec.h +++ b/lib/ui/painting/multi_frame_codec.h @@ -44,6 +44,7 @@ class MultiFrameCodec : public Codec { const std::shared_ptr generator_; const int frameCount_; const int repetitionCount_; + bool is_impeller_enabled_ = false; // The non-const members and functions below here are only read or written // to on the IO thread. They are not safe to access or write on the UI @@ -55,9 +56,11 @@ class MultiFrameCodec : public Codec { // The index of the last decoded required frame. int lastRequiredFrameIndex_ = -1; - sk_sp GetNextFrameImage( + sk_sp GetNextFrameImage( fml::WeakPtr resourceContext, - const std::shared_ptr& gpu_disable_sync_switch); + const std::shared_ptr& gpu_disable_sync_switch, + std::shared_ptr impeller_context_, + fml::RefPtr unref_queue); void GetNextFrameAndInvokeCallback( std::unique_ptr callback, @@ -65,7 +68,8 @@ class MultiFrameCodec : public Codec { fml::WeakPtr resourceContext, fml::RefPtr unref_queue, const std::shared_ptr& gpu_disable_sync_switch, - size_t trace_id); + size_t trace_id, + std::shared_ptr impeller_context_); }; // Shared across the UI and IO task runners.