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 307 of file image_decoder_impeller.cc.

313 : ImageDecoder(runners, std::move(concurrent_task_runner), io_manager),
314 wide_gamut_enabled_(wide_gamut_enabled),
315 gpu_disabled_switch_(gpu_disabled_switch) {
316 std::promise<std::shared_ptr<impeller::Context>> context_promise;
317 context_ = context_promise.get_future();
319 [promise = std::move(context_promise), io_manager]() mutable {
320 if (io_manager) {
321 promise.set_value(io_manager->GetImpellerContext());
322 } else {
323 promise.set_value(nullptr);
324 }
325 }));
326}
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 668 of file image_decoder_impeller.cc.

670 {
671 FML_DCHECK(descriptor);
672 FML_DCHECK(p_result);
673
674 // Wrap the result callback so that it can be invoked from any thread.
675 auto raw_descriptor = descriptor.get();
676 raw_descriptor->AddRef();
677 ImageResult result = [p_result, //
678 raw_descriptor, //
679 ui_runner = runners_.GetUITaskRunner() //
680 ](const auto& image, const auto& decode_error) {
681 ui_runner->PostTask([raw_descriptor, p_result, image, decode_error]() {
682 raw_descriptor->Release();
683 p_result(std::move(image), decode_error);
684 });
685 };
686
687 concurrent_task_runner_->PostTask(
688 [raw_descriptor, //
689 context = context_.get(), //
690 options,
691 io_runner = runners_.GetIOTaskRunner(), //
692 result,
693 wide_gamut_enabled = wide_gamut_enabled_, //
694 gpu_disabled_switch = gpu_disabled_switch_]() {
695#if FML_OS_IOS_SIMULATOR
696 // No-op backend.
697 if (!context) {
698 return;
699 }
700#endif // FML_OS_IOS_SIMULATOR
701
702 if (!context) {
703 result(nullptr, "No Impeller context is available");
704 return;
705 }
706 auto max_size_supported =
707 context->GetResourceAllocator()->GetMaxTextureSizeSupported();
708
709 // Always decompress on the concurrent runner.
710 auto bitmap_result = DecompressTexture(
711 raw_descriptor, options, max_size_supported,
712 /*supports_wide_gamut=*/wide_gamut_enabled &&
713 context->GetCapabilities()->SupportsExtendedRangeFormats(),
714 context->GetCapabilities(), context->GetResourceAllocator());
715 if (!bitmap_result.ok()) {
716 result(nullptr, std::string(bitmap_result.status().message()));
717 return;
718 }
719
720 auto upload_texture_and_invoke_result = [result, context, bitmap_result,
721 gpu_disabled_switch]() {
722 UploadTextureToPrivate(result, context, //
723 bitmap_result->device_buffer, //
724 bitmap_result->image_info, //
725 bitmap_result->resize_info, //
726 gpu_disabled_switch //
727 );
728 };
729 // The I/O image uploads are not threadsafe on GLES.
730 if (context->GetBackendType() ==
732 io_runner->PostTask(upload_texture_and_invoke_result);
733 } else {
734 upload_texture_and_invoke_result();
735 }
736 });
737}
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 331 of file image_decoder_impeller.cc.

337 {
338 TRACE_EVENT0("impeller", __FUNCTION__);
339 if (!descriptor) {
340 std::string decode_error("Invalid descriptor (should never happen)");
341 FML_DLOG(ERROR) << decode_error;
342 return absl::InvalidArgumentError(decode_error);
343 }
344
345 const SkISize source_size = SkISize::Make(descriptor->image_info().width,
346 descriptor->image_info().height);
347 const SkISize target_size =
348 SkISize::Make(std::min(max_texture_size.width,
349 static_cast<int64_t>(options.target_width)),
350 std::min(max_texture_size.height,
351 static_cast<int64_t>(options.target_height)));
352
353 // Fast path for when the input requires no decompressing or conversion.
354 if (!descriptor->is_compressed() && source_size == target_size &&
355 IsZeroOpConversion(descriptor->image_info().format,
356 options.target_format)) {
359 desc.size = descriptor->data()->size();
360 std::shared_ptr<impeller::DeviceBuffer> buffer =
361 allocator->CreateBuffer(desc);
362 if (!buffer) {
363 return absl::ResourceExhaustedError("Could not create buffer for image.");
364 }
365 sk_sp<SkData> data = descriptor->data();
366 memcpy(buffer->OnGetContents(), data->bytes(), data->size());
367 buffer->Flush();
368
369 return ImageDecoderImpeller::DecompressResult{
370 .device_buffer = std::move(buffer),
371 .image_info =
372 {
373 .size =
374 impeller::ISize(source_size.width(), source_size.height()),
375 .format = ToImpellerPixelFormat(options.target_format),
376 },
377 };
378 }
379
380 SkISize decode_size = source_size;
381 if (descriptor->is_compressed()) {
382 decode_size = descriptor->get_scaled_dimensions(std::max(
383 static_cast<float>(target_size.width()) / source_size.width(),
384 static_cast<float>(target_size.height()) / source_size.height()));
385 }
386
387 const SkImageInfo base_image_info =
388 ImageDescriptor::ToSkImageInfo(descriptor->image_info());
389 const absl::StatusOr<SkImageInfo> image_info = CreateImageInfo(
390 base_image_info, decode_size, supports_wide_gamut, options.target_format);
391
392 if (!image_info.ok()) {
393 return image_info.status();
394 }
395
396 if (!ToPixelFormat(image_info.value().colorType()).has_value()) {
397 std::string decode_error =
398 std::format("Codec pixel format is not supported (SkColorType={})",
399 static_cast<int>(image_info.value().colorType()));
400 FML_DLOG(ERROR) << decode_error;
401 return absl::InvalidArgumentError(decode_error);
402 }
403
404 absl::StatusOr<DecodedBitmap> decoded = DecodeToBitmap(
405 descriptor, image_info.value(), base_image_info, allocator);
406 if (!decoded.ok()) {
407 return decoded.status();
408 }
409
410 absl::StatusOr<DecodedBitmap> premultiplied =
411 HandlePremultiplication(decoded->bitmap, decoded->allocator, allocator);
412 if (!premultiplied.ok()) {
413 return premultiplied.status();
414 }
415 std::shared_ptr<SkBitmap> bitmap = premultiplied->bitmap;
416 std::shared_ptr<ImpellerAllocator> bitmap_allocator =
417 premultiplied->allocator;
418
419 if (source_size.width() > max_texture_size.width ||
420 source_size.height() > max_texture_size.height ||
421 !capabilities->SupportsTextureToTextureBlits()) {
422 return ResizeOnCpu(bitmap, target_size, allocator);
423 }
424
425 std::shared_ptr<impeller::DeviceBuffer> buffer =
426 bitmap_allocator->GetDeviceBuffer();
427 if (!buffer) {
428 return absl::InternalError("Unable to get device buffer");
429 }
430 buffer->Flush();
431
432 std::optional<SkImageInfo> resize_info =
433 bitmap->dimensions() == target_size
434 ? std::nullopt
435 : std::optional<SkImageInfo>(
436 image_info.value().makeDimensions(target_size));
437
438 absl::StatusOr<ImageDecoderImpeller::ImageInfo> decoded_image_info =
439 ToImageInfo(bitmap->info());
440 if (!decoded_image_info.ok()) {
441 return decoded_image_info.status();
442 }
443
444 return ImageDecoderImpeller::DecompressResult{
445 .device_buffer = std::move(buffer),
446 .image_info = decoded_image_info.value(),
447 .resize_info = resize_info};
448}
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 288 of file image_decoder_impeller.cc.

289 {
290 switch (type) {
291 case kRGBA_8888_SkColorType:
293 case kBGRA_8888_SkColorType:
295 case kRGBA_F16_SkColorType:
297 case kBGR_101010x_XR_SkColorType:
299 case kRGBA_F32_SkColorType:
301 default:
302 return std::nullopt;
303 }
304 return std::nullopt;
305}
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 565 of file image_decoder_impeller.cc.

571 {
572 TRACE_EVENT0("impeller", __FUNCTION__);
573 if (!context) {
574 result(nullptr, "No Impeller context is available");
575 return;
576 }
577 if (!buffer) {
578 result(nullptr, "No Impeller device buffer is available");
579 return;
580 }
581
582 gpu_disabled_switch->Execute(
584 .SetIfFalse([&result, context, buffer, image_info, resize_info] {
585 sk_sp<DlImage> image;
586 std::string decode_error;
587 std::tie(image, decode_error) = std::tie(image, decode_error) =
588 UnsafeUploadTextureToPrivate(context, buffer, image_info,
589 resize_info);
590 result(image, decode_error);
591 })
592 .SetIfTrue([&result, context, buffer, image_info, resize_info] {
593 auto result_ptr = std::make_shared<ImageResult>(std::move(result));
594 context->StoreTaskForGPU(
595 [result_ptr, context, buffer, image_info, resize_info]() {
596 sk_sp<DlImage> image;
597 std::string decode_error;
598 std::tie(image, decode_error) = UnsafeUploadTextureToPrivate(
599 context, buffer, image_info, resize_info);
600 (*result_ptr)(image, decode_error);
601 },
602 [result_ptr]() {
603 (*result_ptr)(
604 nullptr,
605 "Image upload failed due to loss of GPU access.");
606 });
607 }));
608}
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 611 of file image_decoder_impeller.cc.

613 {
614 TRACE_EVENT0("impeller", __FUNCTION__);
615 if (!context) {
616 return std::make_pair(nullptr, "No Impeller context is available");
617 }
618 if (!bitmap) {
619 return std::make_pair(nullptr, "No texture bitmap is available");
620 }
621 const auto image_info = bitmap->info();
622 const auto pixel_format = ToPixelFormat(image_info.colorType());
623 if (!pixel_format) {
624 std::string decode_error(
625 std::format("Unsupported pixel format (SkColorType={})",
626 static_cast<int>(image_info.colorType())));
627 FML_DLOG(ERROR) << decode_error;
628 return std::make_pair(nullptr, decode_error);
629 }
630
631 impeller::TextureDescriptor texture_descriptor;
633 texture_descriptor.format = pixel_format.value();
634 texture_descriptor.size = {image_info.width(), image_info.height()};
635 texture_descriptor.mip_count = 1;
636
637 auto texture =
638 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
639 if (!texture) {
640 std::string decode_error("Could not create Impeller texture.");
641 FML_DLOG(ERROR) << decode_error;
642 return std::make_pair(nullptr, decode_error);
643 }
644
645 auto mapping = std::make_shared<fml::NonOwnedMapping>(
646 reinterpret_cast<const uint8_t*>(bitmap->getAddr(0, 0)), // data
647 texture_descriptor.GetByteSizeOfBaseMipLevel(), // size
648 [bitmap](auto, auto) mutable { bitmap.reset(); } // proc
649 );
650
651 if (!texture->SetContents(mapping)) {
652 std::string decode_error("Could not copy contents into Impeller texture.");
653 FML_DLOG(ERROR) << decode_error;
654 return std::make_pair(nullptr, decode_error);
655 }
656
657 texture->SetLabel(
658 std::format("ui.Image({})", static_cast<const void*>(texture.get()))
659 .c_str());
660
661 context->DisposeThreadLocalCachedResources();
662
663 return std::make_pair(impeller::DlImageImpeller::Make(std::move(texture)),
664 std::string());
665}
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: