[Impeller] Support multi-frame codecs (#36792)
diff --git a/lib/ui/painting/image_decoder_impeller.cc b/lib/ui/painting/image_decoder_impeller.cc
index 31a5ab0..4130f37 100644
--- a/lib/ui/painting/image_decoder_impeller.cc
+++ b/lib/ui/painting/image_decoder_impeller.cc
@@ -137,7 +137,7 @@
return scaled_bitmap;
}
-static sk_sp<DlImage> UploadTexture(
+sk_sp<DlImage> ImageDecoderImpeller::UploadTexture(
const std::shared_ptr<impeller::Context>& context,
std::shared_ptr<SkBitmap> bitmap) {
TRACE_EVENT0("impeller", __FUNCTION__);
diff --git a/lib/ui/painting/image_decoder_impeller.h b/lib/ui/painting/image_decoder_impeller.h
index 0d1afcf..fdaa0a6 100644
--- a/lib/ui/painting/image_decoder_impeller.h
+++ b/lib/ui/painting/image_decoder_impeller.h
@@ -37,6 +37,10 @@
SkISize target_size,
impeller::ISize max_texture_size);
+ static sk_sp<DlImage> UploadTexture(
+ const std::shared_ptr<impeller::Context>& context,
+ std::shared_ptr<SkBitmap> bitmap);
+
private:
using FutureContext = std::shared_future<std::shared_ptr<impeller::Context>>;
FutureContext context_;
diff --git a/lib/ui/painting/multi_frame_codec.cc b/lib/ui/painting/multi_frame_codec.cc
index 986c2f5..a292025 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 @@
ImageGenerator::kInfinitePlayCount
? -1
: generator_->GetPlayCount() - 1),
+ is_impeller_enabled_(UIDartState::Current()->IsImpellerEnabled()),
nextFrameIndex_(0) {}
static void InvokeNextFrameCallback(
@@ -77,9 +81,11 @@
return true;
}
-sk_sp<SkImage> MultiFrameCodec::State::GetNextFrameImage(
+sk_sp<DlImage> MultiFrameCodec::State::GetNextFrameImage(
fml::WeakPtr<GrDirectContext> resourceContext,
- const std::shared_ptr<const fml::SyncSwitch>& gpu_disable_sync_switch) {
+ const std::shared_ptr<const fml::SyncSwitch>& gpu_disable_sync_switch,
+ std::shared_ptr<impeller::Context> impeller_context_,
+ fml::RefPtr<flutter::SkiaUnrefQueue> unref_queue) {
SkBitmap bitmap = SkBitmap();
SkImageInfo info = generator_->GetInfo().makeColorType(kN32_SkColorType);
if (info.alphaType() == kUnpremul_SkAlphaType) {
@@ -125,30 +131,45 @@
lastRequiredFrame_ = std::make_unique<SkBitmap>(bitmap);
lastRequiredFrameIndex_ = nextFrameIndex_;
}
- sk_sp<SkImage> result;
+#if IMPELLER_SUPPORTS_RENDERING
+ if (is_impeller_enabled_) {
+ sk_sp<DlImage> 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<SkBitmap>(bitmap));
+ }));
+
+ return result;
+ }
+#endif // IMPELLER_SUPPORTS_RENDERING
+
+ sk_sp<SkImage> 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 @@
fml::WeakPtr<GrDirectContext> resourceContext,
fml::RefPtr<flutter::SkiaUnrefQueue> unref_queue,
const std::shared_ptr<const fml::SyncSwitch>& gpu_disable_sync_switch,
- size_t trace_id) {
+ size_t trace_id,
+ std::shared_ptr<impeller::Context> impeller_context) {
fml::RefPtr<CanvasImage> image = nullptr;
int duration = 0;
- sk_sp<SkImage> skImage =
- GetNextFrameImage(std::move(resourceContext), gpu_disable_sync_switch);
- if (skImage) {
+ sk_sp<DlImage> 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 @@
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 3ccf8c7..3cb42b0 100644
--- a/lib/ui/painting/multi_frame_codec.h
+++ b/lib/ui/painting/multi_frame_codec.h
@@ -44,6 +44,7 @@
const std::shared_ptr<ImageGenerator> 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 @@
// The index of the last decoded required frame.
int lastRequiredFrameIndex_ = -1;
- sk_sp<SkImage> GetNextFrameImage(
+ sk_sp<DlImage> GetNextFrameImage(
fml::WeakPtr<GrDirectContext> resourceContext,
- const std::shared_ptr<const fml::SyncSwitch>& gpu_disable_sync_switch);
+ const std::shared_ptr<const fml::SyncSwitch>& gpu_disable_sync_switch,
+ std::shared_ptr<impeller::Context> impeller_context_,
+ fml::RefPtr<flutter::SkiaUnrefQueue> unref_queue);
void GetNextFrameAndInvokeCallback(
std::unique_ptr<DartPersistentValue> callback,
@@ -65,7 +68,8 @@
fml::WeakPtr<GrDirectContext> resourceContext,
fml::RefPtr<flutter::SkiaUnrefQueue> unref_queue,
const std::shared_ptr<const fml::SyncSwitch>& gpu_disable_sync_switch,
- size_t trace_id);
+ size_t trace_id,
+ std::shared_ptr<impeller::Context> impeller_context_);
};
// Shared across the UI and IO task runners.