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

Commit 4f1522d

Browse files
committed
[Impeller] Implement 'ui.Image.toByteData()'
1 parent 896ea42 commit 4f1522d

11 files changed

+373
-92
lines changed

ci/licenses_golden/licenses_flutter

+4
Original file line numberDiff line numberDiff line change
@@ -1713,7 +1713,11 @@ FILE: ../../../flutter/lib/ui/painting/image_descriptor.h
17131713
FILE: ../../../flutter/lib/ui/painting/image_dispose_unittests.cc
17141714
FILE: ../../../flutter/lib/ui/painting/image_encoding.cc
17151715
FILE: ../../../flutter/lib/ui/painting/image_encoding.h
1716+
FILE: ../../../flutter/lib/ui/painting/image_encoding_impeller.cc
1717+
FILE: ../../../flutter/lib/ui/painting/image_encoding_impeller.h
17161718
FILE: ../../../flutter/lib/ui/painting/image_encoding_impl.h
1719+
FILE: ../../../flutter/lib/ui/painting/image_encoding_skia.cc
1720+
FILE: ../../../flutter/lib/ui/painting/image_encoding_skia.h
17171721
FILE: ../../../flutter/lib/ui/painting/image_encoding_unittests.cc
17181722
FILE: ../../../flutter/lib/ui/painting/image_filter.cc
17191723
FILE: ../../../flutter/lib/ui/painting/image_filter.h

impeller/display_list/display_list_image_impeller.cc

+7-4
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@
99

1010
namespace impeller {
1111

12-
sk_sp<DlImageImpeller> DlImageImpeller::Make(std::shared_ptr<Texture> texture) {
12+
sk_sp<DlImageImpeller> DlImageImpeller::Make(std::shared_ptr<Texture> texture,
13+
OwningContext owning_context) {
1314
if (!texture) {
1415
return nullptr;
1516
}
16-
return sk_sp<DlImageImpeller>(new DlImageImpeller(std::move(texture)));
17+
return sk_sp<DlImageImpeller>(
18+
new DlImageImpeller(std::move(texture), owning_context));
1719
}
1820

1921
sk_sp<DlImageImpeller> DlImageImpeller::MakeFromYUVTextures(
@@ -33,8 +35,9 @@ sk_sp<DlImageImpeller> DlImageImpeller::MakeFromYUVTextures(
3335
return impeller::DlImageImpeller::Make(snapshot->texture);
3436
}
3537

36-
DlImageImpeller::DlImageImpeller(std::shared_ptr<Texture> texture)
37-
: texture_(std::move(texture)) {}
38+
DlImageImpeller::DlImageImpeller(std::shared_ptr<Texture> texture,
39+
OwningContext owning_context)
40+
: texture_(std::move(texture)), owning_context_(owning_context) {}
3841

3942
// |DlImage|
4043
DlImageImpeller::~DlImageImpeller() = default;

impeller/display_list/display_list_image_impeller.h

+9-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ class AiksContext;
1414

1515
class DlImageImpeller final : public flutter::DlImage {
1616
public:
17-
static sk_sp<DlImageImpeller> Make(std::shared_ptr<Texture> texture);
17+
static sk_sp<DlImageImpeller> Make(
18+
std::shared_ptr<Texture> texture,
19+
OwningContext owning_context = OwningContext::kIO);
1820

1921
static sk_sp<DlImageImpeller> MakeFromYUVTextures(
2022
AiksContext* aiks_context,
@@ -43,10 +45,15 @@ class DlImageImpeller final : public flutter::DlImage {
4345
// |DlImage|
4446
size_t GetApproximateByteSize() const override;
4547

48+
// |DlImage|
49+
OwningContext owning_context() const override { return owning_context_; }
50+
4651
private:
4752
std::shared_ptr<Texture> texture_;
53+
OwningContext owning_context_;
4854

49-
explicit DlImageImpeller(std::shared_ptr<Texture> texture);
55+
explicit DlImageImpeller(std::shared_ptr<Texture> texture,
56+
OwningContext owning_context = OwningContext::kIO);
5057

5158
FML_DISALLOW_COPY_AND_ASSIGN(DlImageImpeller);
5259
};

lib/ui/BUILD.gn

+4
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ source_set("ui") {
5353
"painting/image_encoding.cc",
5454
"painting/image_encoding.h",
5555
"painting/image_encoding_impl.h",
56+
"painting/image_encoding_skia.cc",
57+
"painting/image_encoding_skia.h",
5658
"painting/image_filter.cc",
5759
"painting/image_filter.h",
5860
"painting/image_generator.cc",
@@ -167,6 +169,8 @@ source_set("ui") {
167169
"painting/display_list_deferred_image_gpu_impeller.h",
168170
"painting/image_decoder_impeller.cc",
169171
"painting/image_decoder_impeller.h",
172+
"painting/image_encoding_impeller.cc",
173+
"painting/image_encoding_impeller.h",
170174
]
171175

172176
deps += [ "//flutter/impeller" ]

lib/ui/painting/display_list_deferred_image_gpu_impeller.h

+5
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ class DlDeferredImageGPUImpeller final : public DlImage {
5050
// |DlImage|
5151
size_t GetApproximateByteSize() const override;
5252

53+
// |DlImage|
54+
OwningContext owning_context() const override {
55+
return OwningContext::kRaster;
56+
}
57+
5358
private:
5459
class ImageWrapper final : public std::enable_shared_from_this<ImageWrapper>,
5560
public ContextListener {

lib/ui/painting/image_encoding.cc

+26-85
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
#include "flutter/fml/make_copyable.h"
1414
#include "flutter/fml/trace_event.h"
1515
#include "flutter/lib/ui/painting/image.h"
16+
#if IMPELLER_SUPPORTS_RENDERING
17+
#include "flutter/lib/ui/painting/image_encoding_impeller.h"
18+
#endif // IMPELLER_SUPPORTS_RENDERING
19+
#include "flutter/lib/ui/painting/image_encoding_skia.h"
1620
#include "third_party/skia/include/core/SkEncodedImageFormat.h"
1721
#include "third_party/tonic/dart_persistent_value.h"
1822
#include "third_party/tonic/logging/dart_invoke.h"
@@ -22,6 +26,9 @@ using tonic::DartInvoke;
2226
using tonic::DartPersistentValue;
2327
using tonic::ToDart;
2428

29+
namespace impeller {
30+
class Context;
31+
} // namespace impeller
2532
namespace flutter {
2633
namespace {
2734

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

63-
void ConvertImageToRaster(
64-
const sk_sp<DlImage>& dl_image,
65-
std::function<void(sk_sp<SkImage>)> encode_task,
66-
const fml::RefPtr<fml::TaskRunner>& raster_task_runner,
67-
const fml::RefPtr<fml::TaskRunner>& io_task_runner,
68-
const fml::WeakPtr<GrDirectContext>& resource_context,
69-
const fml::TaskRunnerAffineWeakPtr<SnapshotDelegate>& snapshot_delegate,
70-
const std::shared_ptr<const fml::SyncSwitch>& is_gpu_disabled_sync_switch) {
71-
// If the owning_context is kRaster, we can't access it on this task runner.
72-
if (dl_image->owning_context() != DlImage::OwningContext::kRaster) {
73-
auto image = dl_image->skia_image();
74-
75-
// Check validity of the image.
76-
if (image == nullptr) {
77-
FML_LOG(ERROR) << "Image was null.";
78-
encode_task(nullptr);
79-
return;
80-
}
81-
82-
auto dimensions = image->dimensions();
83-
84-
if (dimensions.isEmpty()) {
85-
FML_LOG(ERROR) << "Image dimensions were empty.";
86-
encode_task(nullptr);
87-
return;
88-
}
89-
90-
SkPixmap pixmap;
91-
if (image->peekPixels(&pixmap)) {
92-
// This is already a raster image.
93-
encode_task(image);
94-
return;
95-
}
96-
97-
if (sk_sp<SkImage> raster_image = image->makeRasterImage()) {
98-
// The image can be converted to a raster image.
99-
encode_task(raster_image);
100-
return;
101-
}
102-
}
103-
104-
// Cross-context images do not support makeRasterImage. Convert these images
105-
// by drawing them into a surface. This must be done on the raster thread
106-
// to prevent concurrent usage of the image on both the IO and raster threads.
107-
raster_task_runner->PostTask([dl_image, encode_task = std::move(encode_task),
108-
resource_context, snapshot_delegate,
109-
io_task_runner, is_gpu_disabled_sync_switch,
110-
raster_task_runner]() {
111-
auto image = dl_image->skia_image();
112-
if (!image || !snapshot_delegate) {
113-
io_task_runner->PostTask(
114-
[encode_task = encode_task]() mutable { encode_task(nullptr); });
115-
return;
116-
}
117-
118-
sk_sp<SkImage> raster_image =
119-
snapshot_delegate->ConvertToRasterImage(image);
120-
121-
io_task_runner->PostTask([image, encode_task = encode_task,
122-
raster_image = std::move(raster_image),
123-
resource_context, is_gpu_disabled_sync_switch,
124-
owning_context = dl_image->owning_context(),
125-
raster_task_runner]() mutable {
126-
if (!raster_image) {
127-
// The rasterizer was unable to render the cross-context image
128-
// (presumably because it does not have a GrContext). In that case,
129-
// convert the image on the IO thread using the resource context.
130-
raster_image = ConvertToRasterUsingResourceContext(
131-
image, resource_context, is_gpu_disabled_sync_switch);
132-
}
133-
encode_task(raster_image);
134-
if (owning_context == DlImage::OwningContext::kRaster) {
135-
raster_task_runner->PostTask([image = std::move(image)]() {});
136-
}
137-
});
138-
});
139-
}
140-
14170
sk_sp<SkData> CopyImageByteData(const sk_sp<SkImage>& raster_image,
14271
SkColorType color_type,
14372
SkAlphaType alpha_type) {
@@ -221,7 +150,9 @@ void EncodeImageAndInvokeDataCallback(
221150
const fml::RefPtr<fml::TaskRunner>& io_task_runner,
222151
const fml::WeakPtr<GrDirectContext>& resource_context,
223152
const fml::TaskRunnerAffineWeakPtr<SnapshotDelegate>& snapshot_delegate,
224-
const std::shared_ptr<const fml::SyncSwitch>& is_gpu_disabled_sync_switch) {
153+
const std::shared_ptr<const fml::SyncSwitch>& is_gpu_disabled_sync_switch,
154+
const std::shared_ptr<impeller::Context>& impeller_context,
155+
bool is_impeller_enabled) {
225156
auto callback_task = fml::MakeCopyable(
226157
[callback = std::move(callback)](sk_sp<SkData> encoded) mutable {
227158
InvokeDataCallback(std::move(callback), std::move(encoded));
@@ -239,9 +170,17 @@ void EncodeImageAndInvokeDataCallback(
239170
};
240171

241172
FML_DCHECK(image);
242-
ConvertImageToRaster(image, encode_task, raster_task_runner, io_task_runner,
243-
resource_context, snapshot_delegate,
244-
is_gpu_disabled_sync_switch);
173+
#if IMPELLER_SUPPORTS_RENDERING
174+
if (is_impeller_enabled) {
175+
ConvertImageToRasterImpeller(image, encode_task, raster_task_runner,
176+
io_task_runner, is_gpu_disabled_sync_switch,
177+
impeller_context);
178+
return;
179+
}
180+
#endif // IMPELLER_SUPPORTS_RENDERING
181+
ConvertImageToRasterSkia(image, encode_task, raster_task_runner,
182+
io_task_runner, resource_context, snapshot_delegate,
183+
is_gpu_disabled_sync_switch);
245184
}
246185

247186
} // namespace
@@ -272,13 +211,15 @@ Dart_Handle EncodeImage(CanvasImage* canvas_image,
272211
raster_task_runner = task_runners.GetRasterTaskRunner(),
273212
io_task_runner = task_runners.GetIOTaskRunner(),
274213
io_manager = UIDartState::Current()->GetIOManager(),
275-
snapshot_delegate =
276-
UIDartState::Current()->GetSnapshotDelegate()]() mutable {
214+
snapshot_delegate = UIDartState::Current()->GetSnapshotDelegate(),
215+
is_impeller_enabled =
216+
UIDartState::Current()->IsImpellerEnabled()]() mutable {
277217
EncodeImageAndInvokeDataCallback(
278218
image, std::move(callback), image_format, ui_task_runner,
279219
raster_task_runner, io_task_runner,
280220
io_manager->GetResourceContext(), snapshot_delegate,
281-
io_manager->GetIsGpuDisabledSyncSwitch());
221+
io_manager->GetIsGpuDisabledSyncSwitch(),
222+
io_manager->GetImpellerContext(), is_impeller_enabled);
282223
}));
283224

284225
return Dart_Null();

0 commit comments

Comments
 (0)