Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[Impeller] Implement 'ui.Image.toByteData()' #37709

Merged
merged 3 commits into from
Dec 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1771,7 +1771,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
Expand Down
11 changes: 7 additions & 4 deletions impeller/display_list/display_list_image_impeller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@

namespace impeller {

sk_sp<DlImageImpeller> DlImageImpeller::Make(std::shared_ptr<Texture> texture) {
sk_sp<DlImageImpeller> DlImageImpeller::Make(std::shared_ptr<Texture> texture,
OwningContext owning_context) {
if (!texture) {
return nullptr;
}
return sk_sp<DlImageImpeller>(new DlImageImpeller(std::move(texture)));
return sk_sp<DlImageImpeller>(
new DlImageImpeller(std::move(texture), owning_context));
}

sk_sp<DlImageImpeller> DlImageImpeller::MakeFromYUVTextures(
Expand All @@ -33,8 +35,9 @@ sk_sp<DlImageImpeller> DlImageImpeller::MakeFromYUVTextures(
return impeller::DlImageImpeller::Make(snapshot->texture);
}

DlImageImpeller::DlImageImpeller(std::shared_ptr<Texture> texture)
: texture_(std::move(texture)) {}
DlImageImpeller::DlImageImpeller(std::shared_ptr<Texture> texture,
OwningContext owning_context)
: texture_(std::move(texture)), owning_context_(owning_context) {}

// |DlImage|
DlImageImpeller::~DlImageImpeller() = default;
Expand Down
11 changes: 9 additions & 2 deletions impeller/display_list/display_list_image_impeller.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ class AiksContext;

class DlImageImpeller final : public flutter::DlImage {
public:
static sk_sp<DlImageImpeller> Make(std::shared_ptr<Texture> texture);
static sk_sp<DlImageImpeller> Make(
std::shared_ptr<Texture> texture,
OwningContext owning_context = OwningContext::kIO);

static sk_sp<DlImageImpeller> MakeFromYUVTextures(
AiksContext* aiks_context,
Expand Down Expand Up @@ -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> texture_;
OwningContext owning_context_;

explicit DlImageImpeller(std::shared_ptr<Texture> texture);
explicit DlImageImpeller(std::shared_ptr<Texture> texture,
OwningContext owning_context = OwningContext::kIO);

FML_DISALLOW_COPY_AND_ASSIGN(DlImageImpeller);
};
Expand Down
4 changes: 4 additions & 0 deletions lib/ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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" ]
Expand Down
5 changes: 5 additions & 0 deletions lib/ui/painting/display_list_deferred_image_gpu_impeller.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<ImageWrapper>,
public ContextListener {
Expand Down
111 changes: 26 additions & 85 deletions lib/ui/painting/image_encoding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -22,6 +26,9 @@ using tonic::DartInvoke;
using tonic::DartPersistentValue;
using tonic::ToDart;

namespace impeller {
class Context;
} // namespace impeller
namespace flutter {
namespace {

Expand Down Expand Up @@ -60,84 +67,6 @@ void InvokeDataCallback(std::unique_ptr<DartPersistentValue> callback,
DartInvoke(callback->value(), {dart_data});
}

void ConvertImageToRaster(
const sk_sp<DlImage>& dl_image,
std::function<void(sk_sp<SkImage>)> encode_task,
const fml::RefPtr<fml::TaskRunner>& raster_task_runner,
const fml::RefPtr<fml::TaskRunner>& io_task_runner,
const fml::WeakPtr<GrDirectContext>& resource_context,
const fml::TaskRunnerAffineWeakPtr<SnapshotDelegate>& snapshot_delegate,
const std::shared_ptr<const fml::SyncSwitch>& 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<SkImage> 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<SkImage> 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<SkData> CopyImageByteData(const sk_sp<SkImage>& raster_image,
SkColorType color_type,
SkAlphaType alpha_type) {
Expand Down Expand Up @@ -221,7 +150,9 @@ void EncodeImageAndInvokeDataCallback(
const fml::RefPtr<fml::TaskRunner>& io_task_runner,
const fml::WeakPtr<GrDirectContext>& resource_context,
const fml::TaskRunnerAffineWeakPtr<SnapshotDelegate>& snapshot_delegate,
const std::shared_ptr<const fml::SyncSwitch>& is_gpu_disabled_sync_switch) {
const std::shared_ptr<const fml::SyncSwitch>& is_gpu_disabled_sync_switch,
const std::shared_ptr<impeller::Context>& impeller_context,
bool is_impeller_enabled) {
auto callback_task = fml::MakeCopyable(
[callback = std::move(callback)](sk_sp<SkData> encoded) mutable {
InvokeDataCallback(std::move(callback), std::move(encoded));
Expand All @@ -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
Expand Down Expand Up @@ -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();
Expand Down
Loading