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

Commit 06acb0d

Browse files
committed
[Impeller] Support 'ui.Image.toByteData()'
1 parent 96f69a2 commit 06acb0d

14 files changed

+341
-89
lines changed

ci/licenses_golden/licenses_flutter

+4
Original file line numberDiff line numberDiff line change
@@ -1710,7 +1710,11 @@ FILE: ../../../flutter/lib/ui/painting/image_descriptor.h
17101710
FILE: ../../../flutter/lib/ui/painting/image_dispose_unittests.cc
17111711
FILE: ../../../flutter/lib/ui/painting/image_encoding.cc
17121712
FILE: ../../../flutter/lib/ui/painting/image_encoding.h
1713+
FILE: ../../../flutter/lib/ui/painting/image_encoding_impeller.cc
1714+
FILE: ../../../flutter/lib/ui/painting/image_encoding_impeller.h
17131715
FILE: ../../../flutter/lib/ui/painting/image_encoding_impl.h
1716+
FILE: ../../../flutter/lib/ui/painting/image_encoding_skia.cc
1717+
FILE: ../../../flutter/lib/ui/painting/image_encoding_skia.h
17141718
FILE: ../../../flutter/lib/ui/painting/image_encoding_unittests.cc
17151719
FILE: ../../../flutter/lib/ui/painting/image_filter.cc
17161720
FILE: ../../../flutter/lib/ui/painting/image_filter.h

display_list/display_list_image.h

+5
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ class DlImage : public SkRefCnt {
6767

6868
virtual bool isTextureBacked() const = 0;
6969

70+
//----------------------------------------------------------------------------
71+
/// @return Whether this image was created deferred.
72+
///
73+
virtual bool IsDeferred() const { return false; }
74+
7075
//----------------------------------------------------------------------------
7176
/// @return The dimensions of the pixel grid.
7277
///

impeller/renderer/backend/gles/blit_command_gles.cc

+4-2
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,10 @@ std::string BlitCopyTextureToBufferCommandGLES::GetLabel() const {
126126

127127
bool BlitCopyTextureToBufferCommandGLES::Encode(
128128
const ReactorGLES& reactor) const {
129-
if (source->GetTextureDescriptor().format != PixelFormat::kR8G8B8A8UNormInt) {
130-
VALIDATION_LOG << "Only textures with pixel format RGBA are supported yet.";
129+
if (source->GetTextureDescriptor().format != PixelFormat::kR8G8B8A8UNormInt &&
130+
source->GetTextureDescriptor().format != PixelFormat::kB8G8R8A8UNormInt) {
131+
VALIDATION_LOG
132+
<< "Only textures with pixel format RGBA or BGAR are supported yet.";
131133
return false;
132134
}
133135

impeller/renderer/backend/gles/context_gles.cc

+5
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,9 @@ const BackendFeatures& ContextGLES::GetBackendFeatures() const {
142142
return kLegacyBackendFeatures;
143143
}
144144

145+
// |Context|
146+
PixelFormat ContextGLES::GetColorAttachmentPixelFormat() const {
147+
return PixelFormat::kR8G8B8A8UNormInt;
148+
}
149+
145150
} // namespace impeller

impeller/renderer/backend/gles/context_gles.h

+3
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ class ContextGLES final : public Context,
7676
// |Context|
7777
const BackendFeatures& GetBackendFeatures() const override;
7878

79+
// |Context|
80+
PixelFormat GetColorAttachmentPixelFormat() const override;
81+
7982
FML_DISALLOW_COPY_AND_ASSIGN(ContextGLES);
8083
};
8184

impeller/renderer/render_target.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ RenderTarget RenderTarget::CreateOffscreen(const Context& context,
192192

193193
TextureDescriptor color_tex0;
194194
color_tex0.storage_mode = color_storage_mode;
195-
color_tex0.format = PixelFormat::kDefaultColor;
195+
color_tex0.format = context.GetColorAttachmentPixelFormat();
196196
color_tex0.size = size;
197197
color_tex0.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget) |
198198
static_cast<uint64_t>(TextureUsage::kShaderRead);
@@ -257,7 +257,7 @@ RenderTarget RenderTarget::CreateOffscreenMSAA(
257257
color0_tex_desc.storage_mode = color_storage_mode;
258258
color0_tex_desc.type = TextureType::kTexture2DMultisample;
259259
color0_tex_desc.sample_count = SampleCount::kCount4;
260-
color0_tex_desc.format = PixelFormat::kDefaultColor;
260+
color0_tex_desc.format = context.GetColorAttachmentPixelFormat();
261261
color0_tex_desc.size = size;
262262
color0_tex_desc.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget);
263263

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

+3
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ class DlDeferredImageGPUImpeller final : public DlImage {
4444
// |DlImage|
4545
bool isTextureBacked() const override;
4646

47+
// |DlImage|
48+
bool IsDeferred() const override { return true; }
49+
4750
// |DlImage|
4851
SkISize dimensions() const override;
4952

lib/ui/painting/display_list_deferred_image_gpu_skia.h

+3
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ class DlDeferredImageGPUSkia final : public DlImage {
5555
// |DlImage|
5656
bool isTextureBacked() const override;
5757

58+
// |DlImage|
59+
bool IsDeferred() const override { return true; }
60+
5861
// |DlImage|
5962
SkISize dimensions() const override;
6063

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)