Flutter Engine
The Flutter Engine
Public Member Functions | Static Public Member Functions | List of all members
flutter::ImageDecoderSkia Class Referencefinal

#include <image_decoder_skia.h>

Inheritance diagram for flutter::ImageDecoderSkia:
flutter::ImageDecoder

Public Member Functions

 ImageDecoderSkia (const TaskRunners &runners, std::shared_ptr< fml::ConcurrentTaskRunner > concurrent_task_runner, fml::WeakPtr< IOManager > io_manager)
 
 ~ImageDecoderSkia () override
 
void Decode (fml::RefPtr< ImageDescriptor > descriptor, uint32_t target_width, uint32_t target_height, const ImageResult &result) override
 
- Public Member Functions inherited from flutter::ImageDecoder
virtual ~ImageDecoder ()
 
virtual void Decode (fml::RefPtr< ImageDescriptor > descriptor, uint32_t target_width, uint32_t target_height, const ImageResult &result)=0
 
fml::WeakPtr< ImageDecoderGetWeakPtr () const
 

Static Public Member Functions

static sk_sp< SkImageImageFromCompressedData (ImageDescriptor *descriptor, uint32_t target_width, uint32_t target_height, const fml::tracing::TraceFlow &flow)
 
- Static Public Member Functions inherited from flutter::ImageDecoder
static std::unique_ptr< ImageDecoderMake (const Settings &settings, const TaskRunners &runners, std::shared_ptr< fml::ConcurrentTaskRunner > concurrent_task_runner, fml::WeakPtr< IOManager > io_manager, const std::shared_ptr< fml::SyncSwitch > &gpu_disabled_switch)
 

Additional Inherited Members

- Public Types inherited from flutter::ImageDecoder
using ImageResult = std::function< void(sk_sp< DlImage >, std::string)>
 
- Protected Member Functions inherited from flutter::ImageDecoder
 ImageDecoder (const TaskRunners &runners, std::shared_ptr< fml::ConcurrentTaskRunner > concurrent_task_runner, fml::WeakPtr< IOManager > io_manager)
 
- Protected Attributes inherited from flutter::ImageDecoder
TaskRunners runners_
 
std::shared_ptr< fml::ConcurrentTaskRunnerconcurrent_task_runner_
 
fml::WeakPtr< IOManagerio_manager_
 

Detailed Description

Definition at line 15 of file image_decoder_skia.h.

Constructor & Destructor Documentation

◆ ImageDecoderSkia()

flutter::ImageDecoderSkia::ImageDecoderSkia ( const TaskRunners runners,
std::shared_ptr< fml::ConcurrentTaskRunner concurrent_task_runner,
fml::WeakPtr< IOManager io_manager 
)

Definition at line 20 of file image_decoder_skia.cc.

24 : ImageDecoder(runners,
25 std::move(concurrent_task_runner),
26 std::move(io_manager)) {}
ImageDecoder(const TaskRunners &runners, std::shared_ptr< fml::ConcurrentTaskRunner > concurrent_task_runner, fml::WeakPtr< IOManager > io_manager)

◆ ~ImageDecoderSkia()

flutter::ImageDecoderSkia::~ImageDecoderSkia ( )
overridedefault

Member Function Documentation

◆ Decode()

void flutter::ImageDecoderSkia::Decode ( fml::RefPtr< ImageDescriptor descriptor,
uint32_t  target_width,
uint32_t  target_height,
const ImageResult result 
)
overridevirtual

Implements flutter::ImageDecoder.

Definition at line 222 of file image_decoder_skia.cc.

225 {
226 TRACE_EVENT0("flutter", __FUNCTION__);
227 fml::tracing::TraceFlow flow(__FUNCTION__);
228
229 // ImageDescriptors have Dart peers that must be collected on the UI thread.
230 // However, closures in MakeCopyable below capture the descriptor. The
231 // captures of copyable closures may be collected on any of the thread
232 // participating in task execution.
233 //
234 // To avoid this issue, we resort to manually reference counting the
235 // descriptor. Since all task flows invoke the `result` callback, the raw
236 // descriptor is retained in the beginning and released in the `result`
237 // callback.
238 //
239 // `ImageDecoder::Decode` itself is invoked on the UI thread, so the
240 // collection of the smart pointer from which we obtained the raw descriptor
241 // is fine in this scope.
242 auto raw_descriptor = descriptor_ref_ptr.get();
243 raw_descriptor->AddRef();
244
247
248 // Always service the callback (and cleanup the descriptor) on the UI thread.
249 auto result =
250 [callback, raw_descriptor, ui_runner = runners_.GetUITaskRunner()](
251 SkiaGPUObject<SkImage> image, fml::tracing::TraceFlow flow) {
252 ui_runner->PostTask(fml::MakeCopyable(
253 [callback, raw_descriptor, image = std::move(image),
254 flow = std::move(flow)]() mutable {
255 // We are going to terminate the trace flow here. Flows cannot
256 // terminate without a base trace. Add one explicitly.
257 TRACE_EVENT0("flutter", "ImageDecodeCallback");
258 flow.End();
259 callback(DlImageGPU::Make(std::move(image)), {});
260 raw_descriptor->Release();
261 }));
262 };
263
264 if (!raw_descriptor->data() || raw_descriptor->data()->size() == 0) {
265 result({}, std::move(flow));
266 return;
267 }
268
269 concurrent_task_runner_->PostTask(
270 fml::MakeCopyable([raw_descriptor, //
271 io_manager = io_manager_, //
272 io_runner = runners_.GetIOTaskRunner(), //
273 result, //
274 target_width = target_width, //
275 target_height = target_height, //
276 flow = std::move(flow) //
277 ]() mutable {
278 // Step 1: Decompress the image.
279 // On Worker.
280
281 auto decompressed = raw_descriptor->is_compressed()
282 ? ImageFromCompressedData(raw_descriptor, //
283 target_width, //
284 target_height, //
285 flow)
286 : ImageFromDecompressedData(raw_descriptor, //
287 target_width, //
288 target_height, //
289 flow);
290
291 if (!decompressed) {
292 FML_DLOG(ERROR) << "Could not decompress image.";
293 result({}, std::move(flow));
294 return;
295 }
296
297 // Step 2: Update the image to the GPU.
298 // On IO Thread.
299
300 io_runner->PostTask(fml::MakeCopyable([io_manager, decompressed, result,
301 flow =
302 std::move(flow)]() mutable {
303 if (!io_manager) {
304 FML_DLOG(ERROR) << "Could not acquire IO manager.";
305 result({}, std::move(flow));
306 return;
307 }
308
309 // If the IO manager does not have a resource context, the caller
310 // might not have set one or a software backend could be in use.
311 // Either way, just return the image as-is.
312 if (!io_manager->GetResourceContext()) {
313 result({std::move(decompressed), io_manager->GetSkiaUnrefQueue()},
314 std::move(flow));
315 return;
316 }
317
318 auto uploaded =
319 UploadRasterImage(std::move(decompressed), io_manager, flow);
320
321 if (!uploaded.skia_object()) {
322 FML_DLOG(ERROR) << "Could not upload image to the GPU.";
323 result({}, std::move(flow));
324 return;
325 }
326
327 // Finally, all done.
328 result(std::move(uploaded), std::move(flow));
329 }));
330 }));
331}
static sk_sp< DlImageGPU > Make(SkiaGPUObject< SkImage > image)
std::shared_ptr< fml::ConcurrentTaskRunner > concurrent_task_runner_
Definition: image_decoder.h:51
fml::WeakPtr< IOManager > io_manager_
Definition: image_decoder.h:52
fml::RefPtr< fml::TaskRunner > GetUITaskRunner() const
Definition: task_runners.cc:34
fml::RefPtr< fml::TaskRunner > GetIOTaskRunner() const
Definition: task_runners.cc:38
virtual bool RunsTasksOnCurrentThread()
Definition: task_runner.cc:43
if(end==-1)
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
GAsyncResult * result
#define FML_DLOG(severity)
Definition: logging.h:102
#define FML_DCHECK(condition)
Definition: logging.h:103
sk_sp< const SkImage > image
Definition: SkRecords.h:269
static SkiaGPUObject< SkImage > UploadRasterImage(sk_sp< SkImage > image, const fml::WeakPtr< IOManager > &io_manager, const fml::tracing::TraceFlow &flow)
internal::CopyableLambda< T > MakeCopyable(T lambda)
Definition: make_copyable.h:57
#define ERROR(message)
Definition: elf_loader.cc:260
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:131

◆ ImageFromCompressedData()

sk_sp< SkImage > flutter::ImageDecoderSkia::ImageFromCompressedData ( ImageDescriptor descriptor,
uint32_t  target_width,
uint32_t  target_height,
const fml::tracing::TraceFlow flow 
)
static

Definition at line 102 of file image_decoder_skia.cc.

106 {
107 TRACE_EVENT0("flutter", __FUNCTION__);
108 flow.Step(__FUNCTION__);
109
110 if (!descriptor->should_resize(target_width, target_height)) {
111 // No resizing requested. Just decode & rasterize the image.
112 sk_sp<SkImage> image = descriptor->image();
113 return image ? image->makeRasterImage() : nullptr;
114 }
115
116 const SkISize source_dimensions = descriptor->image_info().dimensions();
117 const SkISize resized_dimensions = {static_cast<int32_t>(target_width),
118 static_cast<int32_t>(target_height)};
119
120 auto decode_dimensions = descriptor->get_scaled_dimensions(
121 std::max(static_cast<float>(resized_dimensions.width()) /
122 source_dimensions.width(),
123 static_cast<float>(resized_dimensions.height()) /
124 source_dimensions.height()));
125
126 // If the codec supports efficient sub-pixel decoding, decoded at a resolution
127 // close to the target resolution before resizing.
128 if (decode_dimensions != source_dimensions) {
129 auto scaled_image_info =
130 descriptor->image_info().makeDimensions(decode_dimensions);
131
132 SkBitmap scaled_bitmap;
133 if (!scaled_bitmap.tryAllocPixels(scaled_image_info)) {
134 FML_LOG(ERROR) << "Failed to allocate memory for bitmap of size "
135 << scaled_image_info.computeMinByteSize() << "B";
136 return nullptr;
137 }
138
139 const auto& pixmap = scaled_bitmap.pixmap();
140 if (descriptor->get_pixels(pixmap)) {
141 // Marking this as immutable makes the MakeFromBitmap call share
142 // the pixels instead of copying.
143 scaled_bitmap.setImmutable();
144
145 auto decoded_image = SkImages::RasterFromBitmap(scaled_bitmap);
146 FML_DCHECK(decoded_image);
147 if (!decoded_image) {
149 << "Could not create a scaled image from a scaled bitmap.";
150 return nullptr;
151 }
152 return ResizeRasterImage(decoded_image, resized_dimensions, flow);
153 }
154 }
155
156 auto image = descriptor->image();
157 if (!image) {
158 return nullptr;
159 }
160
161 return ResizeRasterImage(image, resized_dimensions, flow);
162}
void setImmutable()
Definition: SkBitmap.cpp:400
const SkPixmap & pixmap() const
Definition: SkBitmap.h:133
bool tryAllocPixels(const SkImageInfo &info, size_t rowBytes)
Definition: SkBitmap.cpp:271
sk_sp< SkImage > makeRasterImage(GrDirectContext *, CachingHint cachingHint=kDisallow_CachingHint) const
Definition: SkImage.cpp:267
void Step(const char *label=nullptr) const
Definition: trace_event.h:484
#define FML_LOG(severity)
Definition: logging.h:82
static float max(float r, float g, float b)
Definition: hsl.cpp:49
SK_API sk_sp< SkImage > RasterFromBitmap(const SkBitmap &bitmap)
static sk_sp< SkImage > ResizeRasterImage(const sk_sp< SkImage > &image, const SkISize &resized_dimensions, const fml::tracing::TraceFlow &flow)
Definition: SkSize.h:16
constexpr int32_t width() const
Definition: SkSize.h:36
constexpr int32_t height() const
Definition: SkSize.h:37

The documentation for this class was generated from the following files: