From 48cf36f393373189aa6f6161a5569198d1bc5d30 Mon Sep 17 00:00:00 2001 From: xiaowei guan <60122246+xiaowei-guan@users.noreply.github.com> Date: Fri, 30 May 2025 16:49:42 +0800 Subject: [PATCH 1/6] Add render texture for vulkan + impeller (#2) * Merge texture vulkan code and implement texture source * [Tizen] Enable vulkan * Disable xll and fix vulkan build error --- .../flutter/shell/platform/embedder/BUILD.gn | 4 + .../shell/platform/embedder/embedder.cc | 22 ++ .../shell/platform/embedder/embedder.h | 45 ++- .../embedder_external_texture_resolver.cc | 13 + .../embedder_external_texture_resolver.h | 12 + ...embedder_external_texture_source_vulkan.cc | 174 ++++++++++++ .../embedder_external_texture_source_vulkan.h | 67 +++++ .../embedder_external_texture_vulkan.cc | 264 ++++++++++++++++++ .../embedder_external_texture_vulkan.h | 64 +++++ 9 files changed, 664 insertions(+), 1 deletion(-) create mode 100644 engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.cc create mode 100644 engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.h create mode 100644 engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc create mode 100644 engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.h diff --git a/engine/src/flutter/shell/platform/embedder/BUILD.gn b/engine/src/flutter/shell/platform/embedder/BUILD.gn index 789b4d9a82662..0f27d78944849 100644 --- a/engine/src/flutter/shell/platform/embedder/BUILD.gn +++ b/engine/src/flutter/shell/platform/embedder/BUILD.gn @@ -167,6 +167,8 @@ template("embedder_source_set") { if (embedder_enable_vulkan) { sources += [ + "embedder_external_texture_vulkan.cc", + "embedder_external_texture_vulkan.h", "embedder_surface_vulkan.cc", "embedder_surface_vulkan.h", ] @@ -175,6 +177,8 @@ template("embedder_source_set") { sources += [ "embedder_surface_vulkan_impeller.cc", "embedder_surface_vulkan_impeller.h", + "embedder_external_texture_source_vulkan.cc", + "embedder_external_texture_source_vulkan.h", ] } diff --git a/engine/src/flutter/shell/platform/embedder/embedder.cc b/engine/src/flutter/shell/platform/embedder/embedder.cc index d849e7dca12de..85d5bc6c2e85e 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder.cc +++ b/engine/src/flutter/shell/platform/embedder/embedder.cc @@ -2342,6 +2342,28 @@ FlutterEngineResult FlutterEngineInitialize(size_t version, external_texture_metal_callback); } } +#endif +#ifdef SHELL_ENABLE_VULKAN + flutter::EmbedderExternalTextureVulkan::ExternalTextureCallback + external_texture_vulkan_callback; + if (config->type == kVulkan) { + const FlutterVulkanRendererConfig* vulkan_config = &config->vulkan; + if (SAFE_ACCESS(vulkan_config, external_texture_frame_callback, nullptr)) { + external_texture_vulkan_callback = + [ptr = vulkan_config->external_texture_frame_callback, user_data]( + int64_t texture_identifier, size_t width, + size_t height) -> std::unique_ptr { + std::unique_ptr texture = + std::make_unique(); + if (!ptr(user_data, texture_identifier, width, height, texture.get())) { + return nullptr; + } + return texture; + }; + external_texture_resolver = std::make_unique( + external_texture_vulkan_callback); + } + } #endif auto custom_task_runners = SAFE_ACCESS(args, custom_task_runners, nullptr); auto thread_config_callback = [&custom_task_runners]( diff --git a/engine/src/flutter/shell/platform/embedder/embedder.h b/engine/src/flutter/shell/platform/embedder/embedder.h index dfb0896b4ed6b..1f972c7a2cee6 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder.h +++ b/engine/src/flutter/shell/platform/embedder/embedder.h @@ -924,6 +924,9 @@ typedef void* FlutterVulkanQueueHandle; /// Alias for VkImage. typedef uint64_t FlutterVulkanImageHandle; +/// Alias for VkDeviceMemory. +typedef uint64_t FlutterVulkanDeviceMemoryHandle; + typedef struct { /// The size of this struct. Must be sizeof(FlutterVulkanImage). size_t struct_size; @@ -952,6 +955,42 @@ typedef bool (*FlutterVulkanPresentCallback)( void* /* user data */, const FlutterVulkanImage* /* image */); +typedef struct { + /// Handle to the VkImage that is owned by the embedder. The engine will + /// bind this image for writing the frame. + FlutterVulkanImageHandle image; + /// The VkDeviceMemory that backs the iamge. + FlutterVulkanDeviceMemoryHandle image_memory; + /// The VkFormat of the image (for example: VK_FORMAT_R8G8B8A8_UNORM). + uint32_t format; + /// The linear tiling features of the image (for example: + /// VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT). + uint32_t format_features; + + uint64_t alloc_size; + + /// User data to be returned on the invocation of the destruction callback. + void* user_data; + /// Callback invoked (on an engine managed thread) that asks the embedder to + /// collect the texture. + VoidCallback destruction_callback; + /// Optional parameters for texture height/width, default is 0, non-zero means + /// the texture has the specified width/height. + /// Width of the texture. + size_t width; + /// Height of the texture. + size_t height; +} FlutterVulkanTexture; + +/// Callback to provide an external texture for a given texture_id. +/// See: external_texture_frame_callback. +typedef bool (*FlutterVulkanTextureFrameCallback)( + void* /* user data */, + int64_t /* texture identifier */, + size_t /* width */, + size_t /* height */, + FlutterVulkanTexture* /* texture out */); + typedef struct { /// The size of this struct. Must be sizeof(FlutterVulkanRendererConfig). size_t struct_size; @@ -1015,7 +1054,11 @@ typedef struct { /// without any additional synchronization. /// Not used if a FlutterCompositor is supplied in FlutterProjectArgs. FlutterVulkanPresentCallback present_image_callback; - + /// When the embedder specifies that a texture has a frame available, the + /// engine will call this method (on an internal engine managed thread) so + /// that external texture details can be supplied to the engine for subsequent + /// composition. + FlutterVulkanTextureFrameCallback external_texture_frame_callback; } FlutterVulkanRendererConfig; typedef struct { diff --git a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_resolver.cc b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_resolver.cc index 4e4b41b8d4ad2..7a4655b43be81 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_resolver.cc +++ b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_resolver.cc @@ -21,6 +21,12 @@ EmbedderExternalTextureResolver::EmbedderExternalTextureResolver( : metal_callback_(std::move(metal_callback)) {} #endif +#ifdef SHELL_ENABLE_VULKAN +EmbedderExternalTextureResolver::EmbedderExternalTextureResolver( + EmbedderExternalTextureVulkan::ExternalTextureCallback vulkan_callback) + : vulkan_callback_(std::move(vulkan_callback)) {} +#endif + std::unique_ptr EmbedderExternalTextureResolver::ResolveExternalTexture(int64_t texture_id) { #ifdef SHELL_ENABLE_GL @@ -37,6 +43,13 @@ EmbedderExternalTextureResolver::ResolveExternalTexture(int64_t texture_id) { } #endif +#ifdef SHELL_ENABLE_VULKAN + if (vulkan_callback_) { + return std::make_unique( + texture_id, vulkan_callback_); + } +#endif + return nullptr; } diff --git a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_resolver.h b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_resolver.h index 412301736e566..1079a006d6359 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_resolver.h +++ b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_resolver.h @@ -17,6 +17,10 @@ #include "flutter/shell/platform/embedder/embedder_external_texture_metal.h" #endif +#ifdef SHELL_ENABLE_VULKAN +#include "flutter/shell/platform/embedder/embedder_external_texture_vulkan.h" +#endif + namespace flutter { class EmbedderExternalTextureResolver { public: @@ -34,6 +38,11 @@ class EmbedderExternalTextureResolver { EmbedderExternalTextureMetal::ExternalTextureCallback metal_callback); #endif +#ifdef SHELL_ENABLE_VULKAN + explicit EmbedderExternalTextureResolver( + EmbedderExternalTextureVulkan::ExternalTextureCallback vulkan_callback); +#endif + std::unique_ptr ResolveExternalTexture(int64_t texture_id); bool SupportsExternalTextures(); @@ -47,6 +56,9 @@ class EmbedderExternalTextureResolver { EmbedderExternalTextureMetal::ExternalTextureCallback metal_callback_; #endif +#ifdef SHELL_ENABLE_VULKAN + EmbedderExternalTextureVulkan::ExternalTextureCallback vulkan_callback_; +#endif FML_DISALLOW_COPY_AND_ASSIGN(EmbedderExternalTextureResolver); }; } // namespace flutter diff --git a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.cc b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.cc new file mode 100644 index 0000000000000..57f371beff143 --- /dev/null +++ b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.cc @@ -0,0 +1,174 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.h" + +#include "impeller/renderer/backend/vulkan/allocator_vk.h" +#include "impeller/renderer/backend/vulkan/context_vk.h" +#include "impeller/renderer/backend/vulkan/texture_source_vk.h" +#include "impeller/renderer/backend/vulkan/yuv_conversion_library_vk.h" +#include "vulkan/vulkan.hpp" + +namespace flutter { + +EmbedderExternalTextureSourceVulkan::EmbedderExternalTextureSourceVulkan( + const std::shared_ptr& p_context, + FlutterVulkanTexture* embedder_desc) + : TextureSourceVK(ToTextureDescriptor(embedder_desc)) { + const auto& context = impeller::ContextVK::Cast(*p_context); + const auto& device = context.GetDevice(); + texture_image_ = + impeller::vk::Image(reinterpret_cast(embedder_desc->image)); + texture_device_memory_ = impeller::vk::DeviceMemory( + reinterpret_cast(embedder_desc->image_memory)); + // Figure out how to perform YUV conversions. + auto yuv_conversion = CreateYUVConversion(context, embedder_desc); + if (!yuv_conversion || !yuv_conversion->IsValid()) { + VALIDATION_LOG << "Fail to create yuv conversion"; + return; + } + + // Create image view for the newly created image. + if (!CreateTextureImageView(device)) { + VALIDATION_LOG << "Fail to create texture image view"; + return; + } + + yuv_conversion_ = std::move(yuv_conversion); + is_valid_ = true; +} + +impeller::PixelFormat ToPixelFormat(int32_t vk_format) { + switch (vk_format) { + case VK_FORMAT_UNDEFINED: + return impeller::PixelFormat::kUnknown; + case VK_FORMAT_R8G8B8A8_UNORM: + return impeller::PixelFormat::kR8G8B8A8UNormInt; + case VK_FORMAT_R8G8B8A8_SRGB: + return impeller::PixelFormat::kR8G8B8A8UNormIntSRGB; + case VK_FORMAT_B8G8R8A8_UNORM: + return impeller::PixelFormat::kB8G8R8A8UNormInt; + case VK_FORMAT_B8G8R8A8_SRGB: + return impeller::PixelFormat::kB8G8R8A8UNormIntSRGB; + case VK_FORMAT_R32G32B32A32_SFLOAT: + return impeller::PixelFormat::kR32G32B32A32Float; + case VK_FORMAT_R16G16B16A16_SFLOAT: + return impeller::PixelFormat::kR16G16B16A16Float; + case VK_FORMAT_S8_UINT: + return impeller::PixelFormat::kS8UInt; + case VK_FORMAT_D24_UNORM_S8_UINT: + return impeller::PixelFormat::kD24UnormS8Uint; + case VK_FORMAT_D32_SFLOAT_S8_UINT: + return impeller::PixelFormat::kD32FloatS8UInt; + case VK_FORMAT_R8_UNORM: + return impeller::PixelFormat::kR8UNormInt; + case VK_FORMAT_R8G8_UNORM: + return impeller::PixelFormat::kR8G8UNormInt; + default: + return impeller::PixelFormat::kUnknown; + } +} + +impeller::TextureDescriptor +EmbedderExternalTextureSourceVulkan::ToTextureDescriptor( + FlutterVulkanTexture* embedder_desc) { + const auto size = + impeller::ISize{embedder_desc->width, embedder_desc->height}; + impeller::TextureDescriptor desc; + desc.storage_mode = impeller::StorageMode::kDevicePrivate; + desc.format = ToPixelFormat(embedder_desc->format); + desc.size = size; + desc.type = impeller::TextureType::kTexture2D; + desc.sample_count = impeller::SampleCount::kCount1; + desc.compression_type = impeller::CompressionType::kLossless; + desc.mip_count = 1u; + desc.usage = impeller::TextureUsage::kRenderTarget; + return desc; +} + +std::shared_ptr +EmbedderExternalTextureSourceVulkan::CreateYUVConversion( + const impeller::ContextVK& context, + FlutterVulkanTexture* embedder_desc) { + impeller::YUVConversionDescriptorVK conversion_chain; + auto& conversion_info = conversion_chain.get(); + + conversion_info.format = + static_cast(embedder_desc->format); + conversion_info.ycbcrModel = + impeller::vk::SamplerYcbcrModelConversion::eYcbcr709; + conversion_info.ycbcrRange = impeller::vk::SamplerYcbcrRange::eItuFull; + conversion_info.components = {impeller::vk::ComponentSwizzle::eIdentity, + impeller::vk::ComponentSwizzle::eIdentity, + impeller::vk::ComponentSwizzle::eIdentity, + impeller::vk::ComponentSwizzle::eIdentity}; + conversion_info.xChromaOffset = impeller::vk::ChromaLocation::eCositedEven; + conversion_info.yChromaOffset = impeller::vk::ChromaLocation::eCositedEven; + conversion_info.chromaFilter = impeller::vk::Filter::eNearest; + conversion_info.forceExplicitReconstruction = false; + return context.GetYUVConversionLibrary()->GetConversion(conversion_chain); +} + +bool EmbedderExternalTextureSourceVulkan::CreateTextureImageView( + const impeller::vk::Device& device) { + impeller::vk::StructureChain + view_chain; + auto& view_info = view_chain.get(); + view_info.image = texture_image_; + view_info.viewType = impeller::vk::ImageViewType::e2D; + view_info.format = impeller::vk::Format::eR8G8B8A8Srgb; + view_info.subresourceRange.aspectMask = + impeller::vk::ImageAspectFlagBits::eColor; + view_info.subresourceRange.baseMipLevel = 0u; + view_info.subresourceRange.baseArrayLayer = 0u; + view_info.subresourceRange.levelCount = 1; + view_info.subresourceRange.layerCount = 1; + auto image_view = device.createImageViewUnique(view_info); + if (image_view.result != impeller::vk::Result::eSuccess) { + VALIDATION_LOG << "Could not create external image view: " + << impeller::vk::to_string(image_view.result); + return false; + } + texture_image_view_ = std::move(image_view.value); + return true; +} + +// |TextureSourceVK| +EmbedderExternalTextureSourceVulkan::~EmbedderExternalTextureSourceVulkan() = + default; + +bool EmbedderExternalTextureSourceVulkan::IsValid() const { + return is_valid_; +} + +// |TextureSourceVK| +impeller::vk::Image EmbedderExternalTextureSourceVulkan::GetImage() const { + return texture_image_; +} + +// |TextureSourceVK| +impeller::vk::ImageView EmbedderExternalTextureSourceVulkan::GetImageView() + const { + return texture_image_view_.get(); +} + +// |TextureSourceVK| +impeller::vk::ImageView +EmbedderExternalTextureSourceVulkan::GetRenderTargetView() const { + return texture_image_view_.get(); +} + +// |TextureSourceVK| +bool EmbedderExternalTextureSourceVulkan::IsSwapchainImage() const { + return is_swapchain_image_; +} + +// |TextureSourceVK| +std::shared_ptr +EmbedderExternalTextureSourceVulkan::GetYUVConversion() const { + return needs_yuv_conversion_ ? yuv_conversion_ : nullptr; +} + +} // namespace flutter diff --git a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.h b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.h new file mode 100644 index 0000000000000..b64347a46ee5b --- /dev/null +++ b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.h @@ -0,0 +1,67 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_SOURCE_VULKAN_H_ +#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_SOURCE_VULKAN_H_ + +#include "flutter/shell/platform/embedder/embedder.h" +#include "impeller/renderer/backend/vulkan/context_vk.h" +#include "impeller/renderer/backend/vulkan/texture_source_vk.h" +#include "impeller/renderer/backend/vulkan/vk.h" +#include "impeller/renderer/backend/vulkan/yuv_conversion_vk.h" + +namespace flutter { + +class ContextVK; + +class EmbedderExternalTextureSourceVulkan final + : public impeller::TextureSourceVK { + public: + EmbedderExternalTextureSourceVulkan( + const std::shared_ptr& context, + FlutterVulkanTexture* embedder_desc); + + // |TextureSourceVK| + ~EmbedderExternalTextureSourceVulkan() override; + + // |TextureSourceVK| + impeller::vk::Image GetImage() const override; + + // |TextureSourceVK| + impeller::vk::ImageView GetImageView() const override; + + // |TextureSourceVK| + impeller::vk::ImageView GetRenderTargetView() const override; + + bool IsValid() const; + + // |TextureSourceVK| + bool IsSwapchainImage() const override; + + // |TextureSourceVK| + std::shared_ptr GetYUVConversion() const override; + + private: + bool CreateTextureImageView(const impeller::vk::Device& device); + impeller::TextureDescriptor ToTextureDescriptor( + FlutterVulkanTexture* embedder_desc); + std::shared_ptr CreateYUVConversion( + const impeller::ContextVK& context, + FlutterVulkanTexture* embedder_desc); + std::shared_ptr yuv_conversion_ = {}; + bool needs_yuv_conversion_ = false; + bool is_swapchain_image_ = false; + bool is_valid_ = false; + impeller::vk::Image texture_image_; + impeller::vk::DeviceMemory texture_device_memory_; + impeller::vk::UniqueImageView texture_image_view_ = {}; + EmbedderExternalTextureSourceVulkan( + const EmbedderExternalTextureSourceVulkan&) = delete; + EmbedderExternalTextureSourceVulkan& operator=( + const EmbedderExternalTextureSourceVulkan&) = delete; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_SOURCE_VULKAN_H_ diff --git a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc new file mode 100644 index 0000000000000..109d68e00fa2a --- /dev/null +++ b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc @@ -0,0 +1,264 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/shell/platform/embedder/embedder_external_texture_vulkan.h" + +#include "flutter/fml/logging.h" +#include "flutter/impeller/display_list/dl_image_impeller.h" +#include "flutter/impeller/renderer/backend/vulkan/command_buffer_vk.h" +#include "flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.h" +#include "impeller/core/texture_descriptor.h" +#include "impeller/display_list/aiks_context.h" +#include "impeller/renderer/backend/vulkan/texture_vk.h" +#include "impeller/renderer/context.h" +#include "include/core/SkCanvas.h" +#include "include/core/SkPaint.h" +#include "third_party/skia/include/core/SkAlphaType.h" +#include "third_party/skia/include/core/SkColorSpace.h" +#include "third_party/skia/include/core/SkColorType.h" +#include "third_party/skia/include/core/SkImage.h" +#include "third_party/skia/include/core/SkSize.h" +#include "third_party/skia/include/gpu/ganesh/GrBackendSurface.h" +#include "third_party/skia/include/gpu/ganesh/GrDirectContext.h" +#include "third_party/skia/include/gpu/ganesh/SkImageGanesh.h" +#include "third_party/skia/include/gpu/ganesh/vk/GrVkBackendSurface.h" +#include "third_party/skia/include/gpu/ganesh/vk/GrVkTypes.h" + +namespace flutter { +EmbedderExternalTextureVulkan::EmbedderExternalTextureVulkan( + int64_t texture_identifier, + const ExternalTextureCallback& callback) + : Texture(texture_identifier), external_texture_callback_(callback) { + FML_DCHECK(external_texture_callback_); +} + +// |flutter::Texture| +void EmbedderExternalTextureVulkan::Paint(PaintContext& context, + const DlRect& bounds, + bool freeze, + const DlImageSampling sampling) { + if (last_image_ == nullptr) { + last_image_ = + ResolveTexture(Id(), // + context.gr_context, // + context.aiks_context, // + SkISize::Make(bounds.GetWidth(), bounds.GetHeight()) // + ); + } + + DlCanvas* canvas = context.canvas; + const DlPaint* paint = context.paint; + + if (last_image_) { + DlRect image_bounds = DlRect::Make(last_image_->GetBounds()); + if (bounds != image_bounds) { + canvas->DrawImageRect(last_image_, image_bounds, bounds, sampling, paint); + } else { + canvas->DrawImage(last_image_, bounds.GetOrigin(), sampling, paint); + } + } +} + +sk_sp EmbedderExternalTextureVulkan::ResolveTexture( + int64_t texture_id, + GrDirectContext* context, + impeller::AiksContext* aiks_context, + const SkISize& size) { + if (!!aiks_context) { + return ResolveTextureImpeller(texture_id, aiks_context, size); + } else { + return ResolveTextureSkia(texture_id, context, size); + } +} + +bool IsYUVVkFormat(const VkFormat format) { + switch (format) { + case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: + case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: + case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM: + case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM: + case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM: + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16: + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16: + case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM: + case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM: + case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM: + case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM: + case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM: + return true; + + default: + return false; + } +} + +sk_sp EmbedderExternalTextureVulkan::ResolveTextureSkia( + int64_t texture_id, + GrDirectContext* context, + const SkISize& size) { + context->flushAndSubmit(); + context->resetContext(kAll_GrBackendState); + std::unique_ptr texture = + external_texture_callback_(texture_id, size.width(), size.height()); + + if (!texture) { + return nullptr; + } + + size_t width = size.width(); + size_t height = size.height(); + + if (texture->width != 0 && texture->height != 0) { + width = texture->width; + height = texture->height; + } + + GrVkImageInfo image_info = {}; + if (IsYUVVkFormat(static_cast(texture->format))) { + FML_LOG(ERROR) << "try to create YUV image-002....."; + skgpu::VulkanYcbcrConversionInfo ycbcr_info = { + static_cast(texture->format), + 0, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709, + VK_SAMPLER_YCBCR_RANGE_ITU_NARROW, + VK_CHROMA_LOCATION_COSITED_EVEN, + VK_CHROMA_LOCATION_COSITED_EVEN, + VK_FILTER_LINEAR, + false, + static_cast(texture->format_features)}; + + skgpu::VulkanAlloc alloc; + alloc.fMemory = reinterpret_cast(texture->image_memory); + alloc.fOffset = 0; + alloc.fSize = texture->alloc_size; + + image_info = {.fImage = reinterpret_cast(texture->image), + .fAlloc = alloc, + .fImageTiling = VK_IMAGE_TILING_LINEAR, + .fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .fFormat = static_cast(texture->format), + .fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | + VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT, + .fSampleCount = 1, + .fLevelCount = 1, + .fYcbcrConversionInfo = ycbcr_info}; + } else { + image_info = { + .fImage = reinterpret_cast(texture->image), + .fImageTiling = VK_IMAGE_TILING_OPTIMAL, + .fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .fFormat = static_cast(texture->format), + .fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | + VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT, + .fSampleCount = 1, + .fLevelCount = 1, + }; + } + + auto gr_backend_texture = + GrBackendTextures::MakeVk(width, height, image_info); + FML_LOG(ERROR) << "backend texture isValid : " + << gr_backend_texture.isValid(); + // FML_LOG(ERROR) << "backend texture isValid : " << gr_backend_texture.; + SkImages::TextureReleaseProc release_proc = texture->destruction_callback; + auto image = + SkImages::BorrowTextureFrom(context, // context + gr_backend_texture, // texture handle + kTopLeft_GrSurfaceOrigin, // origin + kRGB_888x_SkColorType, // color type + kPremul_SkAlphaType, // alpha type + nullptr, // colorspace + release_proc, // texture release proc + texture->user_data // texture release context + ); + + if (!image) { + // In case Skia rejects the image, call the release proc so that + // embedders can perform collection of intermediates. + if (release_proc) { + release_proc(texture->user_data); + } + FML_LOG(ERROR) << "Could not create external texture....."; + return nullptr; + } + + return DlImage::Make(std::move(image)); +} + +sk_sp EmbedderExternalTextureVulkan::ResolveTextureImpeller( + int64_t texture_id, + impeller::AiksContext* aiks_context, + const SkISize& size) { + std::unique_ptr texture_desc = + external_texture_callback_(texture_id, size.width(), size.height()); + if (!texture_desc) { + return nullptr; + } + + const auto& impeller_context = + impeller::ContextVK::Cast(*aiks_context->GetContext()); + + auto texture_source = std::make_shared( + aiks_context->GetContext(), texture_desc.get()); + + auto texture = std::make_shared( + aiks_context->GetContext(), texture_source); + // Transition the layout to shader read. + { + auto buffer = impeller_context.CreateCommandBuffer(); + impeller::CommandBufferVK& buffer_vk = + impeller::CommandBufferVK::Cast(*buffer); + + impeller::BarrierVK barrier; + barrier.cmd_buffer = buffer_vk.GetCommandBuffer(); + barrier.src_access = impeller::vk::AccessFlagBits::eColorAttachmentWrite | + impeller::vk::AccessFlagBits::eTransferWrite; + barrier.src_stage = + impeller::vk::PipelineStageFlagBits::eColorAttachmentOutput | + impeller::vk::PipelineStageFlagBits::eTransfer; + barrier.dst_access = impeller::vk::AccessFlagBits::eShaderRead; + barrier.dst_stage = impeller::vk::PipelineStageFlagBits::eFragmentShader; + + barrier.new_layout = impeller::vk::ImageLayout::eShaderReadOnlyOptimal; + + if (!texture_source->SetLayout(barrier).ok()) { + return nullptr; + } + if (!impeller_context.GetCommandQueue()->Submit({buffer}).ok()) { + return nullptr; + } + } + + return impeller::DlImageImpeller::Make(texture); +} + +EmbedderExternalTextureVulkan::~EmbedderExternalTextureVulkan() = default; + +// |flutter::Texture| +void EmbedderExternalTextureVulkan::OnGrContextCreated() {} + +// |flutter::Texture| +void EmbedderExternalTextureVulkan::OnGrContextDestroyed() {} + +// |flutter::Texture| +void EmbedderExternalTextureVulkan::MarkNewFrameAvailable() { + last_image_ = nullptr; +} + +// |flutter::Texture| +void EmbedderExternalTextureVulkan::OnTextureUnregistered() {} + +} // namespace flutter \ No newline at end of file diff --git a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.h b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.h new file mode 100644 index 0000000000000..9beffc3295bd9 --- /dev/null +++ b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.h @@ -0,0 +1,64 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_VULKAN_H_ +#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_VULKAN_H_ + +#include "flutter/common/graphics/texture.h" +#include "flutter/fml/macros.h" +#include "flutter/shell/platform/embedder/embedder.h" +#include "include/core/SkTypes.h" +#include "include/gpu/vk/VulkanTypes.h" +#include "third_party/skia/include/core/SkSize.h" + +namespace flutter { + +class EmbedderExternalTextureVulkan : public flutter::Texture { + public: + using ExternalTextureCallback = std::function< + std::unique_ptr(int64_t, size_t, size_t)>; + EmbedderExternalTextureVulkan(int64_t texture_identifier, + const ExternalTextureCallback& callback); + + ~EmbedderExternalTextureVulkan(); + + private: + const ExternalTextureCallback& external_texture_callback_; + + sk_sp last_image_; + + sk_sp ResolveTexture(int64_t texture_id, + GrDirectContext* context, + impeller::AiksContext* aiks_context, + const SkISize& size); + sk_sp ResolveTextureSkia(int64_t texture_id, + GrDirectContext* context, + const SkISize& size); + sk_sp ResolveTextureImpeller(int64_t texture_id, + impeller::AiksContext* aiks_context, + const SkISize& size); + + // |flutter::Texture| + void Paint(PaintContext& context, + const DlRect& bounds, + bool freeze, + const DlImageSampling sampling) override; + + // |flutter::Texture| + void OnGrContextCreated() override; + + // |flutter::Texture| + void OnGrContextDestroyed() override; + + // |flutter::Texture| + void MarkNewFrameAvailable() override; + + // |flutter::Texture| + void OnTextureUnregistered() override; + + FML_DISALLOW_COPY_AND_ASSIGN(EmbedderExternalTextureVulkan); +}; +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_VULKAN_H_ \ No newline at end of file From 05afee01dd5ee02d30bcaeea308fc385247a5b13 Mon Sep 17 00:00:00 2001 From: Xiaowei Guan Date: Wed, 6 Aug 2025 11:04:36 +0800 Subject: [PATCH 2/6] Fix render texture issue --- ...embedder_external_texture_source_vulkan.cc | 49 +++++++++++++++---- .../embedder_external_texture_source_vulkan.h | 5 +- .../embedder_external_texture_vulkan.cc | 14 ++---- 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.cc b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.cc index 57f371beff143..de6d20051c546 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.cc +++ b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.cc @@ -12,6 +12,21 @@ namespace flutter { +bool RequiresYCBCRConversion(impeller::vk::Format format) { + switch (format) { + case impeller::vk::Format::eG8B8R83Plane420Unorm: + case impeller::vk::Format::eG8B8R82Plane420Unorm: + case impeller::vk::Format::eG8B8R83Plane422Unorm: + case impeller::vk::Format::eG8B8R82Plane422Unorm: + case impeller::vk::Format::eG8B8R83Plane444Unorm: + return true; + default: + // NOTE: NOT EXHAUSTIVE. + break; + } + return false; +} + EmbedderExternalTextureSourceVulkan::EmbedderExternalTextureSourceVulkan( const std::shared_ptr& p_context, FlutterVulkanTexture* embedder_desc) @@ -22,15 +37,21 @@ EmbedderExternalTextureSourceVulkan::EmbedderExternalTextureSourceVulkan( impeller::vk::Image(reinterpret_cast(embedder_desc->image)); texture_device_memory_ = impeller::vk::DeviceMemory( reinterpret_cast(embedder_desc->image_memory)); - // Figure out how to perform YUV conversions. - auto yuv_conversion = CreateYUVConversion(context, embedder_desc); - if (!yuv_conversion || !yuv_conversion->IsValid()) { - VALIDATION_LOG << "Fail to create yuv conversion"; - return; + + needs_yuv_conversion_ = RequiresYCBCRConversion( + static_cast(embedder_desc->format)); + std::shared_ptr yuv_conversion; + if (needs_yuv_conversion_) { + // Figure out how to perform YUV conversions. + yuv_conversion = CreateYUVConversion(context, embedder_desc); + if (!yuv_conversion || !yuv_conversion->IsValid()) { + VALIDATION_LOG << "Fail to create yuv conversion"; + return; + } } // Create image view for the newly created image. - if (!CreateTextureImageView(device)) { + if (!CreateTextureImageView(device, embedder_desc, yuv_conversion)) { VALIDATION_LOG << "Fail to create texture image view"; return; } @@ -111,24 +132,32 @@ EmbedderExternalTextureSourceVulkan::CreateYUVConversion( } bool EmbedderExternalTextureSourceVulkan::CreateTextureImageView( - const impeller::vk::Device& device) { + const impeller::vk::Device& device, + FlutterVulkanTexture* embedder_desc, + const std::shared_ptr& yuv_conversion_wrapper) { impeller::vk::StructureChain view_chain; auto& view_info = view_chain.get(); view_info.image = texture_image_; view_info.viewType = impeller::vk::ImageViewType::e2D; - view_info.format = impeller::vk::Format::eR8G8B8A8Srgb; + view_info.format = static_cast(embedder_desc->format); view_info.subresourceRange.aspectMask = impeller::vk::ImageAspectFlagBits::eColor; view_info.subresourceRange.baseMipLevel = 0u; view_info.subresourceRange.baseArrayLayer = 0u; view_info.subresourceRange.levelCount = 1; view_info.subresourceRange.layerCount = 1; + + if (RequiresYCBCRConversion( + static_cast(embedder_desc->format))) { + view_chain.get().conversion = + yuv_conversion_wrapper->GetConversion(); + } else { + view_chain.unlink(); + } auto image_view = device.createImageViewUnique(view_info); if (image_view.result != impeller::vk::Result::eSuccess) { - VALIDATION_LOG << "Could not create external image view: " - << impeller::vk::to_string(image_view.result); return false; } texture_image_view_ = std::move(image_view.value); diff --git a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.h b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.h index b64347a46ee5b..57bad4034fe59 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.h +++ b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.h @@ -43,7 +43,10 @@ class EmbedderExternalTextureSourceVulkan final std::shared_ptr GetYUVConversion() const override; private: - bool CreateTextureImageView(const impeller::vk::Device& device); + bool CreateTextureImageView( + const impeller::vk::Device& device, + FlutterVulkanTexture* embedder_desc, + const std::shared_ptr& yuv_conversion_wrapper); impeller::TextureDescriptor ToTextureDescriptor( FlutterVulkanTexture* embedder_desc); std::shared_ptr CreateYUVConversion( diff --git a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc index 109d68e00fa2a..05d8a8e583db8 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc +++ b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc @@ -124,15 +124,14 @@ sk_sp EmbedderExternalTextureVulkan::ResolveTextureSkia( GrVkImageInfo image_info = {}; if (IsYUVVkFormat(static_cast(texture->format))) { - FML_LOG(ERROR) << "try to create YUV image-002....."; skgpu::VulkanYcbcrConversionInfo ycbcr_info = { static_cast(texture->format), 0, VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709, - VK_SAMPLER_YCBCR_RANGE_ITU_NARROW, + VK_SAMPLER_YCBCR_RANGE_ITU_FULL, VK_CHROMA_LOCATION_COSITED_EVEN, VK_CHROMA_LOCATION_COSITED_EVEN, - VK_FILTER_LINEAR, + VK_FILTER_NEAREST, false, static_cast(texture->format_features)}; @@ -144,10 +143,9 @@ sk_sp EmbedderExternalTextureVulkan::ResolveTextureSkia( image_info = {.fImage = reinterpret_cast(texture->image), .fAlloc = alloc, .fImageTiling = VK_IMAGE_TILING_LINEAR, - .fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .fImageLayout = VK_IMAGE_LAYOUT_PREINITIALIZED, .fFormat = static_cast(texture->format), - .fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | + .fImageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, .fSampleCount = 1, @@ -170,9 +168,6 @@ sk_sp EmbedderExternalTextureVulkan::ResolveTextureSkia( auto gr_backend_texture = GrBackendTextures::MakeVk(width, height, image_info); - FML_LOG(ERROR) << "backend texture isValid : " - << gr_backend_texture.isValid(); - // FML_LOG(ERROR) << "backend texture isValid : " << gr_backend_texture.; SkImages::TextureReleaseProc release_proc = texture->destruction_callback; auto image = SkImages::BorrowTextureFrom(context, // context @@ -191,7 +186,6 @@ sk_sp EmbedderExternalTextureVulkan::ResolveTextureSkia( if (release_proc) { release_proc(texture->user_data); } - FML_LOG(ERROR) << "Could not create external texture....."; return nullptr; } From 7c3b7f30fe3c8954eec64b2367bea461a70bc3fc Mon Sep 17 00:00:00 2001 From: Xiaowei Guan Date: Mon, 22 Sep 2025 14:53:19 +0800 Subject: [PATCH 3/6] Remove not used code --- .../shell/platform/embedder/embedder.h | 6 -- .../embedder_external_texture_vulkan.cc | 84 +++---------------- .../embedder_external_texture_vulkan.h | 6 +- 3 files changed, 15 insertions(+), 81 deletions(-) diff --git a/engine/src/flutter/shell/platform/embedder/embedder.h b/engine/src/flutter/shell/platform/embedder/embedder.h index 1f972c7a2cee6..505f78f276f74 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder.h +++ b/engine/src/flutter/shell/platform/embedder/embedder.h @@ -963,12 +963,6 @@ typedef struct { FlutterVulkanDeviceMemoryHandle image_memory; /// The VkFormat of the image (for example: VK_FORMAT_R8G8B8A8_UNORM). uint32_t format; - /// The linear tiling features of the image (for example: - /// VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT). - uint32_t format_features; - - uint64_t alloc_size; - /// User data to be returned on the invocation of the destruction callback. void* user_data; /// Callback invoked (on an engine managed thread) that asks the embedder to diff --git a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc index 05d8a8e583db8..d274f65f8224a 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc +++ b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc @@ -72,35 +72,6 @@ sk_sp EmbedderExternalTextureVulkan::ResolveTexture( } } -bool IsYUVVkFormat(const VkFormat format) { - switch (format) { - case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: - case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: - case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM: - case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM: - case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM: - case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16: - case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16: - case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16: - case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16: - case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16: - case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16: - case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16: - case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16: - case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16: - case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16: - case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM: - case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM: - case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM: - case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM: - case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM: - return true; - - default: - return false; - } -} - sk_sp EmbedderExternalTextureVulkan::ResolveTextureSkia( int64_t texture_id, GrDirectContext* context, @@ -122,49 +93,18 @@ sk_sp EmbedderExternalTextureVulkan::ResolveTextureSkia( height = texture->height; } - GrVkImageInfo image_info = {}; - if (IsYUVVkFormat(static_cast(texture->format))) { - skgpu::VulkanYcbcrConversionInfo ycbcr_info = { - static_cast(texture->format), - 0, - VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709, - VK_SAMPLER_YCBCR_RANGE_ITU_FULL, - VK_CHROMA_LOCATION_COSITED_EVEN, - VK_CHROMA_LOCATION_COSITED_EVEN, - VK_FILTER_NEAREST, - false, - static_cast(texture->format_features)}; - - skgpu::VulkanAlloc alloc; - alloc.fMemory = reinterpret_cast(texture->image_memory); - alloc.fOffset = 0; - alloc.fSize = texture->alloc_size; - - image_info = {.fImage = reinterpret_cast(texture->image), - .fAlloc = alloc, - .fImageTiling = VK_IMAGE_TILING_LINEAR, - .fImageLayout = VK_IMAGE_LAYOUT_PREINITIALIZED, - .fFormat = static_cast(texture->format), - .fImageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT, - .fSampleCount = 1, - .fLevelCount = 1, - .fYcbcrConversionInfo = ycbcr_info}; - } else { - image_info = { - .fImage = reinterpret_cast(texture->image), - .fImageTiling = VK_IMAGE_TILING_OPTIMAL, - .fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .fFormat = static_cast(texture->format), - .fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT, - .fSampleCount = 1, - .fLevelCount = 1, - }; - } + GrVkImageInfo image_info = { + .fImage = reinterpret_cast(texture->image), + .fImageTiling = VK_IMAGE_TILING_OPTIMAL, + .fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .fFormat = static_cast(texture->format), + .fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | + VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT, + .fSampleCount = 1, + .fLevelCount = 1, + }; auto gr_backend_texture = GrBackendTextures::MakeVk(width, height, image_info); diff --git a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.h b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.h index 9beffc3295bd9..dca65f3039cc2 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.h +++ b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.h @@ -41,9 +41,9 @@ class EmbedderExternalTextureVulkan : public flutter::Texture { // |flutter::Texture| void Paint(PaintContext& context, - const DlRect& bounds, - bool freeze, - const DlImageSampling sampling) override; + const DlRect& bounds, + bool freeze, + const DlImageSampling sampling) override; // |flutter::Texture| void OnGrContextCreated() override; From 474b4c72617f01325fc0f582c5070f37e1ff50a1 Mon Sep 17 00:00:00 2001 From: Xiaowei Guan Date: Tue, 23 Sep 2025 10:41:27 +0800 Subject: [PATCH 4/6] Fix build erro for arm64 --- .../embedder/embedder_external_texture_source_vulkan.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.cc b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.cc index de6d20051c546..31a959f9ba0c5 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.cc +++ b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.cc @@ -95,7 +95,8 @@ impeller::TextureDescriptor EmbedderExternalTextureSourceVulkan::ToTextureDescriptor( FlutterVulkanTexture* embedder_desc) { const auto size = - impeller::ISize{embedder_desc->width, embedder_desc->height}; + impeller::ISize{static_cast(embedder_desc->width), + static_cast(embedder_desc->height)}; impeller::TextureDescriptor desc; desc.storage_mode = impeller::StorageMode::kDevicePrivate; desc.format = ToPixelFormat(embedder_desc->format); From b522e7b7254d4f17b274b17a90b9462c249eabac Mon Sep 17 00:00:00 2001 From: Xiaowei Guan Date: Tue, 23 Sep 2025 11:05:34 +0800 Subject: [PATCH 5/6] Add new line end of file --- .../embedder/embedder_external_texture_vulkan.cc | 9 +++------ .../platform/embedder/embedder_external_texture_vulkan.h | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc index d274f65f8224a..ced35eb6d5e85 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc +++ b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc @@ -40,11 +40,8 @@ void EmbedderExternalTextureVulkan::Paint(PaintContext& context, const DlImageSampling sampling) { if (last_image_ == nullptr) { last_image_ = - ResolveTexture(Id(), // - context.gr_context, // - context.aiks_context, // - SkISize::Make(bounds.GetWidth(), bounds.GetHeight()) // - ); + ResolveTexture(Id(), context.gr_context, context.aiks_context, + SkISize::Make(bounds.GetWidth(), bounds.GetHeight())); } DlCanvas* canvas = context.canvas; @@ -195,4 +192,4 @@ void EmbedderExternalTextureVulkan::MarkNewFrameAvailable() { // |flutter::Texture| void EmbedderExternalTextureVulkan::OnTextureUnregistered() {} -} // namespace flutter \ No newline at end of file +} // namespace flutter diff --git a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.h b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.h index dca65f3039cc2..07611b4b729bf 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.h +++ b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.h @@ -61,4 +61,4 @@ class EmbedderExternalTextureVulkan : public flutter::Texture { }; } // namespace flutter -#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_VULKAN_H_ \ No newline at end of file +#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_VULKAN_H_ From 1819708bbd1042372f6de7119662dbd567d7485f Mon Sep 17 00:00:00 2001 From: Xiaowei Guan Date: Fri, 26 Sep 2025 13:11:30 +0800 Subject: [PATCH 6/6] Add Vulkan implementation for SupportsExternalTextures method --- engine/src/flutter/shell/platform/embedder/embedder.cc | 9 ++++----- .../embedder/embedder_external_texture_resolver.cc | 10 ++++++++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/engine/src/flutter/shell/platform/embedder/embedder.cc b/engine/src/flutter/shell/platform/embedder/embedder.cc index 85d5bc6c2e85e..dfcaf15a2705f 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder.cc +++ b/engine/src/flutter/shell/platform/embedder/embedder.cc @@ -2344,13 +2344,12 @@ FlutterEngineResult FlutterEngineInitialize(size_t version, } #endif #ifdef SHELL_ENABLE_VULKAN - flutter::EmbedderExternalTextureVulkan::ExternalTextureCallback - external_texture_vulkan_callback; if (config->type == kVulkan) { const FlutterVulkanRendererConfig* vulkan_config = &config->vulkan; - if (SAFE_ACCESS(vulkan_config, external_texture_frame_callback, nullptr)) { - external_texture_vulkan_callback = - [ptr = vulkan_config->external_texture_frame_callback, user_data]( + if (auto callback = SAFE_ACCESS(vulkan_config, + external_texture_frame_callback, nullptr)) { + auto external_texture_vulkan_callback = + [ptr = callback, user_data]( int64_t texture_identifier, size_t width, size_t height) -> std::unique_ptr { std::unique_ptr texture = diff --git a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_resolver.cc b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_resolver.cc index 7a4655b43be81..2dcef86b2061c 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_resolver.cc +++ b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_resolver.cc @@ -45,8 +45,8 @@ EmbedderExternalTextureResolver::ResolveExternalTexture(int64_t texture_id) { #ifdef SHELL_ENABLE_VULKAN if (vulkan_callback_) { - return std::make_unique( - texture_id, vulkan_callback_); + return std::make_unique(texture_id, + vulkan_callback_); } #endif @@ -66,6 +66,12 @@ bool EmbedderExternalTextureResolver::SupportsExternalTextures() { } #endif +#ifdef SHELL_ENABLE_VULKAN + if (vulkan_callback_) { + return true; + } +#endif + return false; }