Flutter Engine
flutter::ImageDecoder Class Reference

#include <image_decoder.h>

Public Types

using ImageResult = std::function< void(SkiaGPUObject< SkImage >)>
 

Public Member Functions

 ImageDecoder (TaskRunners runners, std::shared_ptr< fml::ConcurrentTaskRunner > concurrent_task_runner, fml::WeakPtr< IOManager > io_manager)
 
 ~ImageDecoder ()
 
void Decode (fml::RefPtr< ImageDescriptor > descriptor, uint32_t target_width, uint32_t target_height, const ImageResult &result)
 
fml::WeakPtr< ImageDecoderGetWeakPtr () const
 

Detailed Description

Definition at line 32 of file image_decoder.h.

Member Typedef Documentation

◆ ImageResult

Definition at line 41 of file image_decoder.h.

Constructor & Destructor Documentation

◆ ImageDecoder()

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

Definition at line 14 of file image_decoder.cc.

References FML_DCHECK, flutter::TaskRunners::GetUITaskRunner(), flutter::TaskRunners::IsValid(), fml::TaskRunner::RunsTasksOnCurrentThread(), and ~ImageDecoder().

18  : runners_(std::move(runners)),
19  concurrent_task_runner_(std::move(concurrent_task_runner)),
20  io_manager_(std::move(io_manager)),
21  weak_factory_(this) {
22  FML_DCHECK(runners_.IsValid());
24  << "The image decoder must be created & collected on the UI thread.";
25 }
fml::WeakPtr< IOManager > io_manager_
bool IsValid() const
Definition: task_runners.cc:46
#define FML_DCHECK(condition)
Definition: logging.h:86
fml::RefPtr< fml::TaskRunner > GetUITaskRunner() const
Definition: task_runners.cc:34
virtual bool RunsTasksOnCurrentThread()
Definition: task_runner.cc:43

◆ ~ImageDecoder()

flutter::ImageDecoder::~ImageDecoder ( )
default

Referenced by ImageDecoder().

Member Function Documentation

◆ Decode()

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

Definition at line 219 of file image_decoder.cc.

References callback, fml::tracing::TraceFlow::End(), FML_DCHECK, FML_DLOG, fml::RefPtr< T >::get(), flutter::TaskRunners::GetIOTaskRunner(), flutter::TaskRunners::GetUITaskRunner(), flutter::ImageFromCompressedData(), flutter::ImageFromDecompressedData(), fml::MakeCopyable(), result, fml::TaskRunner::RunsTasksOnCurrentThread(), TRACE_EVENT0, and flutter::UploadRasterImage().

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

◆ GetWeakPtr()

fml::WeakPtr< ImageDecoder > flutter::ImageDecoder::GetWeakPtr ( ) const

Definition at line 330 of file image_decoder.cc.

Referenced by flutter::Engine::Engine(), and flutter::Engine::GetImageDecoderWeakPtr().

330  {
331  return weak_factory_.GetWeakPtr();
332 }

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