Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
flutter::ImageDecoderImpeller Class Referencefinal

#include <image_decoder_impeller.h>

Inheritance diagram for flutter::ImageDecoderImpeller:
flutter::ImageDecoder

Classes

struct  DecompressResult
 
struct  ImageInfo
 

Public Member Functions

 ImageDecoderImpeller (const TaskRunners &runners, std::shared_ptr< fml::ConcurrentTaskRunner > concurrent_task_runner, const fml::WeakPtr< IOManager > &io_manager, bool supports_wide_gamut, const std::shared_ptr< fml::SyncSwitch > &gpu_disabled_switch)
 
 ~ImageDecoderImpeller () override
 
void Decode (fml::RefPtr< ImageDescriptor > descriptor, const Options &options, const ImageResult &result) override
 
- Public Member Functions inherited from flutter::ImageDecoder
virtual ~ImageDecoder ()
 
fml::TaskRunnerAffineWeakPtr< ImageDecoderGetWeakPtr () const
 

Static Public Member Functions

static std::optional< impeller::PixelFormatToPixelFormat (SkColorType type)
 
static absl::StatusOr< DecompressResultDecompressTexture (ImageDescriptor *descriptor, const ImageDecoder::Options &options, impeller::ISize max_texture_size, bool supports_wide_gamut, const std::shared_ptr< const impeller::Capabilities > &capabilities, const std::shared_ptr< impeller::Allocator > &allocator)
 
static void UploadTextureToPrivate (ImageResult result, const std::shared_ptr< impeller::Context > &context, const std::shared_ptr< impeller::DeviceBuffer > &buffer, const ImageInfo &image_info, const std::optional< SkImageInfo > &resize_info, const std::shared_ptr< const fml::SyncSwitch > &gpu_disabled_switch)
 Create a device private texture from the provided host buffer.
 
static std::pair< sk_sp< DlImage >, std::string > UploadTextureToStorage (const std::shared_ptr< impeller::Context > &context, std::shared_ptr< SkBitmap > bitmap)
 Create a texture from the provided bitmap.
 
- 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, const fml::WeakPtr< IOManager > &io_manager, const std::shared_ptr< fml::SyncSwitch > &gpu_disabled_switch)
 

Additional Inherited Members

- Public Types inherited from flutter::ImageDecoder
enum  TargetPixelFormat {
  kUnknown ,
  kDontCare ,
  kR32G32B32A32Float ,
  kR32Float
}
 
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 43 of file image_decoder_impeller.h.

Constructor & Destructor Documentation

◆ ImageDecoderImpeller()

flutter::ImageDecoderImpeller::ImageDecoderImpeller ( const TaskRunners runners,
std::shared_ptr< fml::ConcurrentTaskRunner concurrent_task_runner,
const fml::WeakPtr< IOManager > &  io_manager,
bool  supports_wide_gamut,
const std::shared_ptr< fml::SyncSwitch > &  gpu_disabled_switch 
)

Definition at line 309 of file image_decoder_impeller.cc.

315 : ImageDecoder(runners, std::move(concurrent_task_runner), io_manager),
316 wide_gamut_enabled_(wide_gamut_enabled),
317 gpu_disabled_switch_(gpu_disabled_switch) {
318 std::promise<std::shared_ptr<impeller::Context>> context_promise;
319 context_ = context_promise.get_future();
321 [promise = std::move(context_promise), io_manager]() mutable {
322 if (io_manager) {
323 promise.set_value(io_manager->GetImpellerContext());
324 } else {
325 promise.set_value(nullptr);
326 }
327 }));
328}
ImageDecoder(const TaskRunners &runners, std::shared_ptr< fml::ConcurrentTaskRunner > concurrent_task_runner, fml::WeakPtr< IOManager > io_manager)
fml::RefPtr< fml::TaskRunner > GetIOTaskRunner() const
virtual void PostTask(const fml::closure &task) override
internal::CopyableLambda< T > MakeCopyable(T lambda)

References flutter::TaskRunners::GetIOTaskRunner(), fml::MakeCopyable(), fml::TaskRunner::PostTask(), and flutter::ImageDecoder::runners_.

◆ ~ImageDecoderImpeller()

flutter::ImageDecoderImpeller::~ImageDecoderImpeller ( )
overridedefault

Member Function Documentation

◆ Decode()

void flutter::ImageDecoderImpeller::Decode ( fml::RefPtr< ImageDescriptor descriptor,
const Options options,
const ImageResult result 
)
overridevirtual

Implements flutter::ImageDecoder.

Definition at line 670 of file image_decoder_impeller.cc.

672 {
673 FML_DCHECK(descriptor);
674 FML_DCHECK(p_result);
675
676 // Wrap the result callback so that it can be invoked from any thread.
677 auto raw_descriptor = descriptor.get();
678 raw_descriptor->AddRef();
679 ImageResult result = [p_result, //
680 raw_descriptor, //
681 ui_runner = runners_.GetUITaskRunner() //
682 ](const auto& image, const auto& decode_error) {
683 ui_runner->PostTask([raw_descriptor, p_result, image, decode_error]() {
684 raw_descriptor->Release();
685 p_result(std::move(image), decode_error);
686 });
687 };
688
689 concurrent_task_runner_->PostTask(
690 [raw_descriptor, //
691 context = context_.get(), //
692 options,
693 io_runner = runners_.GetIOTaskRunner(), //
694 result,
695 wide_gamut_enabled = wide_gamut_enabled_, //
696 gpu_disabled_switch = gpu_disabled_switch_]() {
697#if FML_OS_IOS_SIMULATOR
698 // No-op backend.
699 if (!context) {
700 return;
701 }
702#endif // FML_OS_IOS_SIMULATOR
703
704 if (!context) {
705 result(nullptr, "No Impeller context is available");
706 return;
707 }
708 auto max_size_supported =
709 context->GetResourceAllocator()->GetMaxTextureSizeSupported();
710
711 // Always decompress on the concurrent runner.
712 auto bitmap_result = DecompressTexture(
713 raw_descriptor, options, max_size_supported,
714 /*supports_wide_gamut=*/wide_gamut_enabled &&
715 context->GetCapabilities()->SupportsExtendedRangeFormats(),
716 context->GetCapabilities(), context->GetResourceAllocator());
717 if (!bitmap_result.ok()) {
718 result(nullptr, std::string(bitmap_result.status().message()));
719 return;
720 }
721
722 auto upload_texture_and_invoke_result = [result, context, bitmap_result,
723 gpu_disabled_switch]() {
724 UploadTextureToPrivate(result, context, //
725 bitmap_result->device_buffer, //
726 bitmap_result->image_info, //
727 bitmap_result->resize_info, //
728 gpu_disabled_switch //
729 );
730 };
731 // The I/O image uploads are not threadsafe on GLES.
732 if (context->GetBackendType() ==
734 io_runner->PostTask(upload_texture_and_invoke_result);
735 } else {
736 upload_texture_and_invoke_result();
737 }
738 });
739}
std::function< void(sk_sp< DlImage >, std::string)> ImageResult
std::shared_ptr< fml::ConcurrentTaskRunner > concurrent_task_runner_
static absl::StatusOr< DecompressResult > DecompressTexture(ImageDescriptor *descriptor, const ImageDecoder::Options &options, impeller::ISize max_texture_size, bool supports_wide_gamut, const std::shared_ptr< const impeller::Capabilities > &capabilities, const std::shared_ptr< impeller::Allocator > &allocator)
static void UploadTextureToPrivate(ImageResult result, const std::shared_ptr< impeller::Context > &context, const std::shared_ptr< impeller::DeviceBuffer > &buffer, const ImageInfo &image_info, const std::optional< SkImageInfo > &resize_info, const std::shared_ptr< const fml::SyncSwitch > &gpu_disabled_switch)
Create a device private texture from the provided host buffer.
fml::RefPtr< fml::TaskRunner > GetUITaskRunner() const
T * get() const
Definition ref_ptr.h:117
FlutterVulkanImage * image
#define FML_DCHECK(condition)
Definition logging.h:122

References FML_DCHECK, fml::RefPtr< T >::get(), image, and impeller::Context::kOpenGLES.

◆ DecompressTexture()

absl::StatusOr< ImageDecoderImpeller::DecompressResult > flutter::ImageDecoderImpeller::DecompressTexture ( ImageDescriptor descriptor,
const ImageDecoder::Options options,
impeller::ISize  max_texture_size,
bool  supports_wide_gamut,
const std::shared_ptr< const impeller::Capabilities > &  capabilities,
const std::shared_ptr< impeller::Allocator > &  allocator 
)
static

Definition at line 333 of file image_decoder_impeller.cc.

339 {
340 TRACE_EVENT0("impeller", __FUNCTION__);
341 if (!descriptor) {
342 std::string decode_error("Invalid descriptor (should never happen)");
343 FML_DLOG(ERROR) << decode_error;
344 return absl::InvalidArgumentError(decode_error);
345 }
346
347 const SkISize source_size = SkISize::Make(descriptor->image_info().width,
348 descriptor->image_info().height);
349 const SkISize target_size =
350 SkISize::Make(std::min(max_texture_size.width,
351 static_cast<int64_t>(options.target_width)),
352 std::min(max_texture_size.height,
353 static_cast<int64_t>(options.target_height)));
354
355 // Fast path for when the input requires no decompressing or conversion.
356 if (!descriptor->is_compressed() && source_size == target_size &&
357 IsZeroOpConversion(descriptor->image_info().format,
358 options.target_format)) {
361 desc.size = descriptor->data()->size();
362 std::shared_ptr<impeller::DeviceBuffer> buffer =
363 allocator->CreateBuffer(desc);
364 if (!buffer) {
365 return absl::ResourceExhaustedError("Could not create buffer for image.");
366 }
367 sk_sp<SkData> data = descriptor->data();
368 memcpy(buffer->OnGetContents(), data->bytes(), data->size());
369 buffer->Flush();
370
371 return ImageDecoderImpeller::DecompressResult{
372 .device_buffer = std::move(buffer),
373 .image_info =
374 {
375 .size =
376 impeller::ISize(source_size.width(), source_size.height()),
377 .format = ToImpellerPixelFormat(options.target_format),
378 },
379 };
380 }
381
382 SkISize decode_size = source_size;
383 if (descriptor->is_compressed()) {
384 decode_size = descriptor->get_scaled_dimensions(std::max(
385 static_cast<float>(target_size.width()) / source_size.width(),
386 static_cast<float>(target_size.height()) / source_size.height()));
387 }
388
389 const SkImageInfo base_image_info =
390 ImageDescriptor::ToSkImageInfo(descriptor->image_info());
391 const absl::StatusOr<SkImageInfo> image_info = CreateImageInfo(
392 base_image_info, decode_size, supports_wide_gamut, options.target_format);
393
394 if (!image_info.ok()) {
395 return image_info.status();
396 }
397
398 if (!ToPixelFormat(image_info.value().colorType()).has_value()) {
399 std::string decode_error =
400 std::format("Codec pixel format is not supported (SkColorType={})",
401 static_cast<int>(image_info.value().colorType()));
402 FML_DLOG(ERROR) << decode_error;
403 return absl::InvalidArgumentError(decode_error);
404 }
405
406 absl::StatusOr<DecodedBitmap> decoded = DecodeToBitmap(
407 descriptor, image_info.value(), base_image_info, allocator);
408 if (!decoded.ok()) {
409 return decoded.status();
410 }
411
412 absl::StatusOr<DecodedBitmap> premultiplied =
413 HandlePremultiplication(decoded->bitmap, decoded->allocator, allocator);
414 if (!premultiplied.ok()) {
415 return premultiplied.status();
416 }
417 std::shared_ptr<SkBitmap> bitmap = premultiplied->bitmap;
418 std::shared_ptr<ImpellerAllocator> bitmap_allocator =
419 premultiplied->allocator;
420
421 if (source_size.width() > max_texture_size.width ||
422 source_size.height() > max_texture_size.height ||
423 !capabilities->SupportsTextureToTextureBlits()) {
424 return ResizeOnCpu(bitmap, target_size, allocator);
425 }
426
427 std::shared_ptr<impeller::DeviceBuffer> buffer =
428 bitmap_allocator->GetDeviceBuffer();
429 if (!buffer) {
430 return absl::InternalError("Unable to get device buffer");
431 }
432 buffer->Flush();
433
434 std::optional<SkImageInfo> resize_info =
435 bitmap->dimensions() == target_size
436 ? std::nullopt
437 : std::optional<SkImageInfo>(
438 image_info.value().makeDimensions(target_size));
439
440 absl::StatusOr<ImageDecoderImpeller::ImageInfo> decoded_image_info =
441 ToImageInfo(bitmap->info());
442 if (!decoded_image_info.ok()) {
443 return decoded_image_info.status();
444 }
445
446 return ImageDecoderImpeller::DecompressResult{
447 .device_buffer = std::move(buffer),
448 .image_info = decoded_image_info.value(),
449 .resize_info = resize_info};
450}
static std::optional< impeller::PixelFormat > ToPixelFormat(SkColorType type)
static SkImageInfo ToSkImageInfo(const ImageInfo &image_info)
#define FML_DLOG(severity)
Definition logging.h:121
std::shared_ptr< SkBitmap > bitmap
std::shared_ptr< ImpellerAllocator > allocator
constexpr impeller::PixelFormat ToImpellerPixelFormat(FlutterGPUPixelFormat value)
Definition formats.h:60
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switch_defs.h:36
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer
Definition switch_defs.h:98
ISize64 ISize
Definition size.h:162
Type height
Definition size.h:29
Type width
Definition size.h:28
#define TRACE_EVENT0(category_group, name)

References allocator, bitmap, flutter::buffer, flutter::ImageDescriptor::data(), flutter::data, flutter::ImageDecoderImpeller::DecompressResult::device_buffer, FML_DLOG, flutter::ImageDecoderImpeller::ImageInfo::format, flutter::ImageDescriptor::get_scaled_dimensions(), impeller::TSize< T >::height, flutter::ImageDescriptor::image_info(), flutter::ImageDescriptor::is_compressed(), impeller::kHostVisible, impeller::DeviceBufferDescriptor::size, impeller::DeviceBufferDescriptor::storage_mode, flutter::ImageDecoder::Options::target_format, flutter::ImageDecoder::Options::target_height, flutter::ImageDecoder::Options::target_width, ToPixelFormat(), flutter::ImageDescriptor::ToSkImageInfo(), TRACE_EVENT0, and impeller::TSize< T >::width.

Referenced by flutter::testing::TEST(), flutter::testing::TEST(), flutter::testing::TEST(), flutter::testing::TEST(), flutter::testing::TEST(), flutter::testing::TEST(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ ToPixelFormat()

std::optional< impeller::PixelFormat > flutter::ImageDecoderImpeller::ToPixelFormat ( SkColorType  type)
static

Definition at line 290 of file image_decoder_impeller.cc.

291 {
292 switch (type) {
293 case kRGBA_8888_SkColorType:
295 case kBGRA_8888_SkColorType:
297 case kRGBA_F16_SkColorType:
299 case kBGR_101010x_XR_SkColorType:
301 case kRGBA_F32_SkColorType:
303 default:
304 return std::nullopt;
305 }
306 return std::nullopt;
307}
GLenum type

References impeller::kB10G10R10XR, impeller::kB8G8R8A8UNormInt, impeller::kR16G16B16A16Float, impeller::kR32G32B32A32Float, impeller::kR8G8B8A8UNormInt, and type.

Referenced by DecompressTexture().

◆ UploadTextureToPrivate()

void flutter::ImageDecoderImpeller::UploadTextureToPrivate ( ImageResult  result,
const std::shared_ptr< impeller::Context > &  context,
const std::shared_ptr< impeller::DeviceBuffer > &  buffer,
const ImageInfo image_info,
const std::optional< SkImageInfo > &  resize_info,
const std::shared_ptr< const fml::SyncSwitch > &  gpu_disabled_switch 
)
static

Create a device private texture from the provided host buffer.

Parameters
resultThe image result closure that accepts the DlImage and any encoding error messages.
contextThe Impeller graphics context.
bufferA host buffer containing the image to be uploaded.
image_infoFormat information about the particular image.
bitmapA bitmap containg the image to be uploaded.
gpu_disabled_switchWhether the GPU is available command encoding.

Definition at line 567 of file image_decoder_impeller.cc.

573 {
574 TRACE_EVENT0("impeller", __FUNCTION__);
575 if (!context) {
576 result(nullptr, "No Impeller context is available");
577 return;
578 }
579 if (!buffer) {
580 result(nullptr, "No Impeller device buffer is available");
581 return;
582 }
583
584 gpu_disabled_switch->Execute(
586 .SetIfFalse([&result, context, buffer, image_info, resize_info] {
587 sk_sp<DlImage> image;
588 std::string decode_error;
589 std::tie(image, decode_error) = std::tie(image, decode_error) =
590 UnsafeUploadTextureToPrivate(context, buffer, image_info,
591 resize_info);
592 result(image, decode_error);
593 })
594 .SetIfTrue([&result, context, buffer, image_info, resize_info] {
595 auto result_ptr = std::make_shared<ImageResult>(std::move(result));
596 context->StoreTaskForGPU(
597 [result_ptr, context, buffer, image_info, resize_info]() {
598 sk_sp<DlImage> image;
599 std::string decode_error;
600 std::tie(image, decode_error) = UnsafeUploadTextureToPrivate(
601 context, buffer, image_info, resize_info);
602 (*result_ptr)(image, decode_error);
603 },
604 [result_ptr]() {
605 (*result_ptr)(
606 nullptr,
607 "Image upload failed due to loss of GPU access.");
608 });
609 }));
610}
Represents the 2 code paths available when calling |SyncSwitchExecute|.
Definition sync_switch.h:35

References flutter::buffer, image, and TRACE_EVENT0.

Referenced by flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ UploadTextureToStorage()

std::pair< sk_sp< DlImage >, std::string > flutter::ImageDecoderImpeller::UploadTextureToStorage ( const std::shared_ptr< impeller::Context > &  context,
std::shared_ptr< SkBitmap >  bitmap 
)
static

Create a texture from the provided bitmap.

Parameters
contextThe Impeller graphics context.
bitmapA bitmap containg the image to be uploaded.
Returns
A DlImage.

Definition at line 613 of file image_decoder_impeller.cc.

615 {
616 TRACE_EVENT0("impeller", __FUNCTION__);
617 if (!context) {
618 return std::make_pair(nullptr, "No Impeller context is available");
619 }
620 if (!bitmap) {
621 return std::make_pair(nullptr, "No texture bitmap is available");
622 }
623 const auto image_info = bitmap->info();
624 const auto pixel_format = ToPixelFormat(image_info.colorType());
625 if (!pixel_format) {
626 std::string decode_error(
627 std::format("Unsupported pixel format (SkColorType={})",
628 static_cast<int>(image_info.colorType())));
629 FML_DLOG(ERROR) << decode_error;
630 return std::make_pair(nullptr, decode_error);
631 }
632
633 impeller::TextureDescriptor texture_descriptor;
635 texture_descriptor.format = pixel_format.value();
636 texture_descriptor.size = {image_info.width(), image_info.height()};
637 texture_descriptor.mip_count = 1;
638
639 auto texture =
640 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
641 if (!texture) {
642 std::string decode_error("Could not create Impeller texture.");
643 FML_DLOG(ERROR) << decode_error;
644 return std::make_pair(nullptr, decode_error);
645 }
646
647 auto mapping = std::make_shared<fml::NonOwnedMapping>(
648 reinterpret_cast<const uint8_t*>(bitmap->getAddr(0, 0)), // data
649 texture_descriptor.GetByteSizeOfBaseMipLevel(), // size
650 [bitmap](auto, auto) mutable { bitmap.reset(); } // proc
651 );
652
653 if (!texture->SetContents(mapping)) {
654 std::string decode_error("Could not copy contents into Impeller texture.");
655 FML_DLOG(ERROR) << decode_error;
656 return std::make_pair(nullptr, decode_error);
657 }
658
659 texture->SetLabel(
660 std::format("ui.Image({})", static_cast<const void*>(texture.get()))
661 .c_str());
662
663 context->DisposeThreadLocalCachedResources();
664
665 return std::make_pair(impeller::DlImageImpeller::Make(std::move(texture)),
666 std::string());
667}
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
FlTexture * texture
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
constexpr size_t GetByteSizeOfBaseMipLevel() const

References bitmap, FML_DLOG, impeller::TextureDescriptor::format, impeller::TextureDescriptor::GetByteSizeOfBaseMipLevel(), impeller::kHostVisible, impeller::DlImageImpeller::Make(), impeller::TextureDescriptor::mip_count, impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, texture, impeller::ToPixelFormat(), and TRACE_EVENT0.

Referenced by flutter::testing::TEST_F().


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