diff --git a/build/skia/ohos/BUILD.gn b/build/skia/ohos/BUILD.gn index 781e92cdcdbcdb64ceb615fa974f58cfe7fb1561..918c4b8ce1c58270010cb72eadca014ebcf38fba 100644 --- a/build/skia/ohos/BUILD.gn +++ b/build/skia/ohos/BUILD.gn @@ -181,6 +181,7 @@ skia_common_defines = [ "SK_FORCE_RASTER_PIPELINE_BLITTER", "SK_LEGACY_SKCODEC_NONE_ENUM", "SK_ENABLE_DUMP_GPU", + "SK_BUILD_FOR_OPENHARMONY", ] # ------------------------------------------------ diff --git a/engine/flutter/vulkan/vulkan_application.cc b/engine/flutter/vulkan/vulkan_application.cc index 06d63b772efe04a2de9713b0f230ffc1b6a475f6..48a515c263fe46e9d407c6b70cbc19775862f8b1 100644 --- a/engine/flutter/vulkan/vulkan_application.cc +++ b/engine/flutter/vulkan/vulkan_application.cc @@ -13,6 +13,7 @@ #endif #include "flutter/vulkan/vulkan_proc_table.h" #include "flutter/vulkan/vulkan_utilities.h" +#include "vulkan/vulkan_ohos.h" namespace vulkan { @@ -33,6 +34,11 @@ VulkanApplication::VulkanApplication( // Configure extensions. + instanceExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); + instanceExtensions.push_back(VK_OPENHARMONY_OHOS_SURFACE_EXTENSION_NAME); + for (const VkExtensionProperties& extension : supported_extensions) { + instanceExtensions.push_back(extension.extensionName); + } if (enable_instance_debugging) { enabled_extensions.emplace_back(VulkanDebugReport::DebugExtensionName()); } @@ -96,8 +102,8 @@ VulkanApplication::VulkanApplication( .pApplicationInfo = &info, .enabledLayerCount = static_cast(enabled_layers.size()), .ppEnabledLayerNames = layers, - .enabledExtensionCount = static_cast(enabled_extensions.size()), - .ppEnabledExtensionNames = extensions, + .enabledExtensionCount = static_cast(instanceExtensions.size()), + .ppEnabledExtensionNames = instanceExtensions.data(), }; // Perform initialization. @@ -273,4 +279,9 @@ bool VulkanApplication::ExtensionSupported( return false; } +std::vector VulkanApplication::GetInstanceExtensions() const +{ + return instanceExtensions; +} + } // namespace vulkan diff --git a/engine/flutter/vulkan/vulkan_application.h b/engine/flutter/vulkan/vulkan_application.h index 2fb0c2e01c185956aec4f75c06999883388ebc78..c0169e6c013e66ee54d46b8b8a7bc7f7b4384ecd 100644 --- a/engine/flutter/vulkan/vulkan_application.h +++ b/engine/flutter/vulkan/vulkan_application.h @@ -44,6 +44,7 @@ class VulkanApplication { std::unique_ptr AcquireFirstCompatibleLogicalDevice() const; + std::vector GetInstanceExtensions() const; private: VulkanProcTable& vk; VulkanHandle instance_; @@ -51,6 +52,7 @@ class VulkanApplication { std::unique_ptr debug_report_; bool valid_; + std::vector instanceExtensions; std::vector GetPhysicalDevices() const; std::vector GetSupportedInstanceExtensions( const VulkanProcTable& vk) const; diff --git a/engine/flutter/vulkan/vulkan_device.cc b/engine/flutter/vulkan/vulkan_device.cc index 3caf2b0eff2de527d3f01cca1f9b74dfb389c48e..ba0bc546dd3bbc388b520c573b36864ad505a120 100644 --- a/engine/flutter/vulkan/vulkan_device.cc +++ b/engine/flutter/vulkan/vulkan_device.cc @@ -96,16 +96,45 @@ VulkanDevice::VulkanDevice(VulkanProcTable& p_vk, VulkanHandle layers[i] = enabled_layers[i].c_str(); } + uint32_t extensionCount = 0; + if (VK_CALL_LOG_ERROR(vk.EnumerateDeviceExtensionProperties(physical_device_, + nullptr, &extensionCount, nullptr)) != VK_SUCCESS) { + LOGE("VK CALL EnumerateDeviceExtensionProperties get extensionCount error!"); + } + std::vector deviceExtensionsOwner(extensionCount); + if (VK_CALL_LOG_ERROR(vk.EnumerateDeviceExtensionProperties(physical_device_, + nullptr, &extensionCount, deviceExtensionsOwner.data())) != VK_SUCCESS) { + LOGE("VK CALL EnumerateDeviceExtensionProperties fill deviceExtensionsOwner error!"); + } + for (auto& extension : extensions) { + deviceExtensions.push_back(extension); + } + for (const VkExtensionProperties& extension : deviceExtensionsOwner) { + deviceExtensions.push_back(extension); + } + memset(&physicalDeviceFeatures2, 0, sizeof(VkPhysicalDeviceFeatures2)); + physicalDeviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + physicalDeviceFeatures2.pNext = nullptr; + void** tailPNext = &physicalDeviceFeatures2.pNext; + + VkPhysicalDeviceSamplerYcbcrConversionFeatures* ycbcrFeatures; + ycbcrFeatures = (VkPhysicalDeviceSamplerYcbcrConversionFeatures*) malloc(sizeof(VkPhysicalDeviceSamplerYcbcrConversionFeatures)); + ycbcrFeatures->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES; + ycbcrFeatures->pNext = nullptr; + *tailPNext = ycbcrFeatures; + tailPNext = &ycbcrFeatures->pNext; + vk.GetPhysicalDeviceFeatures2(physical_device_, &physicalDeviceFeatures2); + const VkDeviceCreateInfo create_info = { .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, - .pNext = nullptr, + .pNext = &physicalDeviceFeatures2, .flags = 0, .queueCreateInfoCount = queue_create.size(), .pQueueCreateInfos = queue_create.data(), .enabledLayerCount = static_cast(enabled_layers.size()), .ppEnabledLayerNames = layers, - .enabledExtensionCount = sizeof(extensions) / sizeof(const char*), - .ppEnabledExtensionNames = extensions, + .enabledExtensionCount = sizeof(deviceExtensions) / sizeof(const char*), + .ppEnabledExtensionNames = deviceExtensions.data(), .pEnabledFeatures = nullptr, }; @@ -272,6 +301,7 @@ VulkanDevice::VulkanDevice(VulkanProcTable& p_vk, VulkanDevice::~VulkanDevice() { #ifdef RS_ENABLE_VK WaitIdle(); + FreeExtensionsMemChain(physicalDeviceFeatures2); #else FML_ALLOW_UNUSED_LOCAL(WaitIdle()); #endif @@ -573,4 +603,21 @@ bool VulkanDevice::QueueSubmit( return true; } +VkPhysicalDeviceFeatures2 VulkanDevice::GetPhysicalDeviceFeatures2() +{ + return &physicalDeviceFeatures2; +} +std::vector VulkanDevice::GetQueueFamilyProperties() +{ + return deviceExtensions; +} +void VulkanDevice::FreeExtensionsMemChain(const VkPhysicalDeviceFeatures2 features2) +{ + void* pNext = features.pNext; + while (pNext) { + void* cur = pNext; + pNext = static_cast(cur)->pNext; + free(cur); + } +} } // namespace vulkan diff --git a/engine/flutter/vulkan/vulkan_device.h b/engine/flutter/vulkan/vulkan_device.h index db9d604f16a7bfa78c300905f987439d11a9aff1..dc2fe07d702ae0247af551d3278c9d2db8daf911 100644 --- a/engine/flutter/vulkan/vulkan_device.h +++ b/engine/flutter/vulkan/vulkan_device.h @@ -39,6 +39,8 @@ class VulkanDevice { void ReleaseDeviceOwnership(); + std::vector GetDeviceExtensions() const; + #ifndef RS_ENABLE_VK FML_WARN_UNUSED_RESULT #endif @@ -83,6 +85,11 @@ class VulkanDevice { #endif bool WaitIdle() const; +#ifndef RS_ENABLE_VK + FML_WARN_UNUSED_RESULT +#endif + VkPhysicalDeviceFeatures2 GetPhysicalDeviceFeatures2() const; + private: VulkanProcTable& vk; VulkanHandle physical_device_; @@ -94,9 +101,14 @@ class VulkanDevice { uint32_t compute_queue_index_; #endif bool valid_; - + struct VKStruct { + VkStructureType sType; + void* pNext; + } + VkPhysicalDeviceFeatures2 physicalDeviceFeatures2{}; + std::vector deviceExtensions; std::vector GetQueueFamilyProperties() const; - + void FreeExtensionsMemChain(const VkPhysicalDeviceFeatures2 features2); #ifndef RS_ENABLE_VK FML_DISALLOW_COPY_AND_ASSIGN(VulkanDevice); #endif diff --git a/engine/flutter/vulkan/vulkan_proc_table.cc b/engine/flutter/vulkan/vulkan_proc_table.cc index 13a2e527fd68a5dc0f6d49dedf541a140ef94411..50edd013001dfd94b47d4e2c25e145d0c856f93e 100644 --- a/engine/flutter/vulkan/vulkan_proc_table.cc +++ b/engine/flutter/vulkan/vulkan_proc_table.cc @@ -117,6 +117,10 @@ bool VulkanProcTable::SetupInstanceProcAddresses( ACQUIRE_PROC(GetPhysicalDeviceSurfaceSupportKHR, handle); ACQUIRE_PROC(DestroySurfaceKHR, handle); ACQUIRE_PROC(CreateOHOSSurfaceOpenHarmony, handle); + ACQUIRE_PROC(GetPhysicalDeviceMemoryProperties2, handle); + ACQUIRE_PROC(BindImageMemory2, handle); + ACQUIRE_PROC(GetPhysicalDeviceFeatures2, handle); + ACQUIRE_PROC(EnumerateDeviceExtensionProperties, handle); #else ACQUIRE_PROC(GetDeviceProcAddr, handle); ACQUIRE_PROC(GetPhysicalDeviceFeatures, handle); @@ -180,6 +184,7 @@ bool VulkanProcTable::SetupDeviceProcAddresses( ACQUIRE_PROC(DestroySwapchainKHR, handle); ACQUIRE_PROC(GetSwapchainImagesKHR, handle); ACQUIRE_PROC(QueuePresentKHR, handle); + ACQUIRE_PROC(GetOHOSNativeBufferPropertiesOpenHarmony, handle); #else #if OS_ANDROID ACQUIRE_PROC(AcquireNextImageKHR, handle); diff --git a/engine/flutter/vulkan/vulkan_proc_table.h b/engine/flutter/vulkan/vulkan_proc_table.h index 9519a6da53bff1f953a58c148034470ace090eb1..c79eefdcba74ee51df51c0c636fa48d9203ec678 100644 --- a/engine/flutter/vulkan/vulkan_proc_table.h +++ b/engine/flutter/vulkan/vulkan_proc_table.h @@ -111,6 +111,11 @@ class VulkanProcTable { DEFINE_PROC(GetSwapchainImagesKHR); DEFINE_PROC(QueuePresentKHR); DEFINE_PROC(CreateOHOSSurfaceOpenHarmony); + DEFINE_PROC(GetOHOSNativeBufferPropertiesOpenHarmony); + DEFINE_PROC(GetPhysicalDeviceMemoryProperties2); + DEFINE_PROC(BindImageMemory2); + DEFINE_PROC(GetPhysicalDeviceFeatures2); + DEFINE_PROC(EnumerateDeviceExtensionProperties); #undef DEFINE_PROC diff --git a/engine/flutter/vulkan/vulkan_window.cc b/engine/flutter/vulkan/vulkan_window.cc index e1052b27b0d6f5ae6b1a08c164a5c04739d6f490..f3bf05dd05c32a76efbfecccbab7040ba120f0bb 100644 --- a/engine/flutter/vulkan/vulkan_window.cc +++ b/engine/flutter/vulkan/vulkan_window.cc @@ -7,6 +7,11 @@ #include #include +#include + +#include "vulkan/vulkan_ohos.h" +#include "driver.h" + #include "flutter/vulkan/vulkan_application.h" #include "flutter/vulkan/vulkan_device.h" #ifdef RS_ENABLE_VK @@ -16,17 +21,20 @@ #include "flutter/vulkan/vulkan_surface.h" #include "flutter/vulkan/vulkan_swapchain.h" #include "third_party/skia/include/gpu/GrContext.h" +#include "third_party/skia/src/gpu/vk/GrVkGpu.h" +#include "third_party/skia/src/gpu/vk/GrContextPriv.h" namespace vulkan { #ifdef RS_ENABLE_VK -VulkanProcTable* VulkanWindow::vk; +std::unique_ptr VulkanWindow::vk; std::unique_ptr VulkanWindow::application_; std::unique_ptr VulkanWindow::logical_device_; std::thread::id VulkanWindow::device_thread_; std::vector> VulkanWindow::shared_fences_; uint32_t VulkanWindow::shared_fence_index_; bool VulkanWindow::presenting_ = false; +GrVkExtensions VulkanWindow::mExtensions; void VulkanWindow::InitializeVulkan(size_t thread_num) { @@ -42,8 +50,7 @@ void VulkanWindow::InitializeVulkan(size_t thread_num) LOGI("First Initialize Vulkan"); device_thread_ = std::this_thread::get_id(); - - vk = new VulkanProcTable(); + vk = std::make_unique(); if (!vk->HasAcquiredMandatoryProcAddresses()) { LOGE("Proc table has not acquired mandatory proc addresses."); return; @@ -51,7 +58,7 @@ void VulkanWindow::InitializeVulkan(size_t thread_num) // Create the application instance. std::vector extensions = { - VK_KHR_SURFACE_SPEC_VERSION, // parent extension + VK_KHR_SURFACE_EXTENSION_NAME, // parent extension VK_OPENHARMONY_OHOS_SURFACE_EXTENSION_NAME // child extension }; @@ -83,6 +90,15 @@ VulkanWindow::VulkanWindow(std::unique_ptr native_surface, LOGE("InitializeVulkan failed"); return; } + GrVkGetProc skiaGetProp = [](const char* proc_name, VkInstance instance, VkDevice device) { + if (device != VK_NULL_HANDLE) { + return vk->GetDeviceProcAddr(device, proc_name); + } + return vk->GetInstanceProcAddr(instance, proc_name); + } + mExtensions.init(skiaGetProp, application_->GetInstance(), logical_device_->GetPhysicalDeviceHandle(), + application_->GetInstanceExtensions().size(), application_->GetInstanceExtensions().data(), + logical_device_->GetDeviceExtensions().size(), logical_device_->GetDeviceExtensions().data()); if (!is_offscreen && (native_surface == nullptr || !native_surface->IsValid())) { LOGE("Native surface is invalid."); @@ -243,6 +259,8 @@ bool VulkanWindow::CreateSkiaBackendContext(GrVkBackendContext* context) { context->fQueue = logical_device_->GetQueueHandle(); context->fGraphicsQueueIndex = logical_device_->GetGraphicsQueueIndex(); context->fMinAPIVersion = application_->GetAPIVersion(); + context->fVkExtensions = &mExtensions; + context->fDeviceFeatures2 = logical_device_->GetPhysicalDeviceFeatures2(); #ifdef RS_ENABLE_VK uint32_t extensionFlags = kKHR_surface_GrVkExtensionFlag; if (!is_offscreen_) { @@ -261,6 +279,73 @@ bool VulkanWindow::CreateSkiaBackendContext(GrVkBackendContext* context) { return true; } +GrBackendFormat VulkanWindow::GetBackendFormat(GrContext* context, OH_NativeBuffer* buffer, int32_t format) +{ + GrBackendApi backend = context->backend(); + if (backend != GrBackendApi::kVulkan) { + LOGE("VulkanWindow::GetBackendFormat backend: %{public}d is not vulkan", backend); + return GrBackendFormat(); + } + switch (format) { + case PIXEL_FMT_RGBA_8888: + return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_UNORM); + case STUB_PIXEL_FMT_RGBA_16161616: + return GrBackendFormat::MakeVk(VK_FORMAT_R16G16B16A16_SFLOAT); + case STUB_PIXEL_FMT_RGBA_1010102: + return GrBackendFormat::MakeVk(VK_FORMAT_A2B10G10R10_UNORM_PACK32); + case PIXEL_FMT_RGBX_8888: + return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_UNORM); + case PIXEL_FMT_RGB_888: + return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8_UNORM); + default: { + return CreateDefaultBackendFormat(context); + } + } +} + +GrBackendFormat VulkanWindow::CreateDefaultBackendFormat(GrContext* context, OH_NativeBuffer* buffer) +{ + GrVkGpu* gpu = static_cast(context->priv().getGpu()); + VkDevice device = gpu->device(); + if (!gpu || !device) { + LOGE("VulkanWindow::CreateDefaultBackendFormat gpu or device is nullptr!"); + GrBackendFormat(); + } + VkOHOSNativeBufferFormatPropertiesOpenHarmony hwbFormatProps; + hwbFormatProps.sType = VK_STRUCTURE_TYPE_OHOS_NATIVE_BUFFER_FORMAT_PROPERTIES_OPENHARMONY; + hwbFormatProps.pNext = nullptr; + + VkOHOSNativeBufferPropertiesOpenHarmony hwbProps; + hwbProps.sType = VK_STRUCTURE_TYPE_OHOS_NATIVE_BUFFER_PROPERTIES_OPENHARMONY; + hwbProps.pNext = &hwbFormatProps; + VkResult result = vk->GetOHOSNativeBufferPropertiesOpenHarmony(device, buffer, &hwbProps); + + if (result != VK_SUCCESSS) { + LOGE("VulkanWindow::CreateDefaultBackendFormat VK_CALL GetOHOSNativeBufferPropertiesOpenHarmony error: + %{public}d", result); + return GrBackendFormat(); + } + + if (hwbFormatProps.format != VK_FORMAT_UNDEFINED) { + LOGE("VulkanWindow::CreateDefaultBackendFormat hwbFormatProps.format is not VK_FORMAT_UNDEFINED"); + return GrBackendFormat(); + } + GrVkYcbcrConversionInfo ycbcrInfo; + ycbcrInfo.fYcbcrModel = hwbFormatProps.suggestYcbcrModel; + ycbcrInfo.fYcbcrRange = hwbFormatProps.suggestYcbcrRange; + ycbcrInfo.fYcbcrXChromaOffset = hwbFormatProps.suggestYcbcrXChromaOffset; + ycbcrInfo.fYcbcrYChromaOffset = hwbFormatProps.suggestYcbcrYChromaOffset; + ycbcrInfo.fForceExplicitReconstruction = VK_FALSE; + ycbcrInfo.fExternalFormat = hwbFormatProps.externalFormat; + ycbcrInfo.fFormatFeatures = hwbFormatProps.formatFeatures; + if (VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_FILTER_BIT & hwbFormatProps.formatFeatures) { + ycbcrInfo.fChromaFilter = VK_FILTER_LINEAR; + } else { + ycbcrInfo.fChromaFilter = VK_FILTER_NEAREST; + } + return GrBackendFormat::MakeVk(ycbcrInfo); +} + sk_sp VulkanWindow::AcquireSurface() { #ifdef RS_ENABLE_VK if (is_offscreen_ || !IsValid()) { @@ -435,6 +520,150 @@ bool VulkanWindow::ResetSharedFence() { } #endif +GrBackendTexture VulkanWindow::GetBackendTexture(int32_t width, int32_t height, int32_t format, OH_NativeBuffer* buffer) +{ + GrContext* context = GetSkiaGrContext(); + if (!context) { + LOGE("VulkanWindow::GetBackendTexture GetSkiaGrContext is nullptr!"); + return GrBackendTexture(); + } + GrBackendFormat backendFormat = GetBackendFormat(context, buffer, format); + GrVkGpu* gpu = static_cast(context->priv().getGpu()); + VkDevice device = gpu->device(); + VkPhysicalDevice physicalDevice = gpu->physicalDevice(); + if (!gpu || !device || !physicalDevice) { + LOGE("VulkanWindow::GetBackendTexture gpu or device or physicalDevice is nullptr!"); + GrBackendTexture(); + } + + VkFormat VkFormat; + backendFormat.asVkFormat(&VkFormat); + + VkResult result; + + VkOHOSNativeBufferFormatPropertiesOpenHarmony hwbFormatProps; + hwbFormatProps.sType = VK_STRUCTURE_TYPE_OHOS_NATIVE_BUFFER_FORMAT_PROPERTIES_OPENHARMONY; + hwbFormatProps.pNext = nullptr; + + VkOHOSNativeBufferPropertiesOpenHarmony hwbProps; + hwbProps.sType = VK_STRUCTURE_TYPE_OHOS_NATIVE_BUFFER_PROPERTIES_OPENHARMONY; + hwbProps.pNext = &hwbFormatProps; + result = vk->GetOHOSNativeBufferPropertiesOpenHarmony(device, buffer, &hwbProps); + + if (result != VK_SUCCESSS) { + LOGE("VulkanWindow::GetBackendTexture VK_CALL GetOHOSNativeBufferPropertiesOpenHarmony error: + %{public}d", result); + return GrBackendTexture(); + } + + VkExternalFormatOpenHarmony externalFormat; + externalFormat.sType = VK_STRUCTURE_TYPE_OHOS_NATIVE_BUFFER_PROPERTIES_OPENHARMONY; + externalFormat.pNext = nullptr; + externalFormat.externalFormat = 0; + + const GrVkYcbcrConversionInfo ycbcrInfo = backendFormat.getVkYcbcrConversionInfo(); + if (!ycbcrInfo) { + LOGE("VulkanWindow::GetBackendTexture ycbcrInfo is nullptr"); + return GrBackendTexture(); + } + + if (hwbFormatProps.format == VK_FORMAT_UNDEFINED) { + externalFormat.externalFormat = hwbFormatProps.externalFormat; + } + + const VkExternalMemoryImageCreateInfo externalMemeoryImageInfo { + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, + &externalFormat, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OHOS_NATIVE_BUFFER_BIT_OPENHARMONY + }; + VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT; + if (vkFormat != VK_FORMAT_UNDEFINED) { + usageFlags = usageFlags | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + usageFlags = usageFlags | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + } + VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL; + const VkImageCreateInfo imageCreateInfo = { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + &externalMemoryImageInfo, + 0, + VK_IMAGE_TYPE_2D, + vkFormat, + {(uint32_t)width, (uint32_t)height, 1}, + 1, + 1, + VK_SAMPLE_COUNT_1_BIT, + tiling, + usageFlags, + VK_SHARING_MODE_EXCLUSIVE, + 0, + 0, + VK_IMAGE_LAYOUT_UNDEFINED + }; + VkImage image; + result = vk->CreateImage(device, &imageCreateInfo, nullptr, &image); + if (result != VK_SUCCESS) { + LOGE("VulkanWindow::GetBackendTexture VK_CALL CreateImage error: + %{public}d", result); + return GrBackendTexture(); + } + + uint32_t typeIndex = 0; + VkImportOHOSNativeBufferInfoOpenHarmony hwbImportInfo; + hwbImportInfo.sType = VK_STRUCTURE_TYPE_IMPORT_OHOS_NATIVE_BUFFER_INFO_OPENHARMONY; + hwbImportInfo.pNext = nullptr; + hwbImportInfo.buffer = buffer; + + VkMemoryDedicatedAllocateInfo dedicatedAllocInfo; + dedicatedAllocInfo.sType = VK_MEMORY_DEDICATED_ALLOCATE_INFO; + dedicatedAllocInfo.pNext = &hwbImportInfo; + dedicatedAllocInfo.image = image; + dedicatedAllocInfo.buffer = buffer; + + VkMemoryAllocateInfo allocateInfo = { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + &dedicatedAllocInfo, + hwbProps.allocationSize, + typeIndex + } + + VkDeviceMemory memory; + result = vk->AllocateMemory(device, &allocateInfo, nullptr, &memory); + if (result != VK_SUCCESS) { + LOGE("VulkanWindow::GetBackendTexture VK_CALL AllocateMemory error: + %{public}d", result); + return GrBackendTexture(); + } + VkBindImageMemoryInfo memoryInfo; + memoryInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; + memoryInfo.pNext = nullptr; + memoryInfo.image = image; + memoryInfo.memory = memory; + memoryInfo.memoryOffset = 0; + result = vk->BindImageMemory2(device, 1, &memoryInfo); + if (result != VK_SUCCESS) { + LOGE("VulkanWindow::GetBackendTexture VK_CALL BindImageMemory2 error: + %{public}d", result); + return GrBackendTexture(); + } + + GrVkAlloc alloc; + alloc.fMemory = memory; + alloc.fOffset = 0; + alloc.fSize = hwbProps.allocationSize; + alloc.fFlags = 0; + + GrVkImageInfo imageInfo; + imageInfo.fImage = image; + imageInfo.fAlloc = alloc; + imageInfo.fImageTiling = tiling; + imageInfo.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageInfo.fFormat = vkFormat; + imageInfo.fLevelCount = 1; + imageInfo.fCurrentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL; + imageInfo.fYcbcrConversionInfo = *ycbcrInfo; + return GrBackendTexture(width, height, imageInfo); +} + bool VulkanWindow::RecreateSwapchain() { #ifdef RS_ENABLE_VK if (is_offscreen_) { @@ -488,5 +717,4 @@ bool VulkanWindow::RecreateSwapchain() { swapchain_ = std::move(swapchain); return true; } - } // namespace vulkan diff --git a/engine/flutter/vulkan/vulkan_window.h b/engine/flutter/vulkan/vulkan_window.h index c2f1b74dfeb3210181d60981375326d890800770..d96a108ac0ec3834aeb96e4210bc82263898c636 100644 --- a/engine/flutter/vulkan/vulkan_window.h +++ b/engine/flutter/vulkan/vulkan_window.h @@ -11,6 +11,8 @@ #include #include +#include + #ifndef RS_ENABLE_VK #include "flutter/fml/compiler_specific.h" #include "flutter/fml/macros.h" @@ -21,6 +23,9 @@ #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/GrContext.h" #include "third_party/skia/include/gpu/vk/GrVkBackendContext.h" +#include "third_party/skia/include/gpu/GrBackendSurface.h" +#include "third_party/skia/include/gpu/vk/GrVkExtensions.h" + namespace vulkan { @@ -60,11 +65,12 @@ class VulkanWindow { static bool WaitForSharedFence(); static bool ResetSharedFence(); #endif + GrBackendTexture GetBackendTexture(int32_t width, int32_t height, int32_t format, OH_NativeBuffer* buffer); private: bool valid_; #ifdef RS_ENABLE_VK - static VulkanProcTable* vk; + static std::unique_ptr vk; static std::unique_ptr application_; static std::unique_ptr logical_device_; bool is_offscreen_ = false; @@ -72,6 +78,7 @@ class VulkanWindow { static std::vector> shared_fences_; static uint32_t shared_fence_index_; static bool presenting_; + static GrVkExtensions mExtensions; #else fml::RefPtr vk; std::unique_ptr application_; @@ -80,11 +87,20 @@ class VulkanWindow { std::unique_ptr surface_; std::unique_ptr swapchain_; sk_sp skia_gr_context_; + enum + { + STUB_PIXEL_FMT_RGBA_16161616 = 0X7fff00001, + STUB_PIXEL_FMT_RGBA_1010102 = 0X7fff00002 + }; bool CreateSkiaGrContext(); bool CreateSkiaBackendContext(GrVkBackendContext* context); + GrBackendFormat GetBackendFormat(GrContext* context, OH_NativeBuffer* buffer, int32_t format); + + GrBackendFormat CreateDefaultBackendFormat(GrContext* context, OH_NativeBuffer* buffer); + #ifndef RS_ENABLE_VK FML_WARN_UNUSED_RESULT #endif diff --git a/skia/include/third_party/vulkan/vulkan/vulkan_core.h b/skia/include/third_party/vulkan/vulkan/vulkan_core.h index 4d8762f8e6d6ffc7aadbd69f538f70dca9fcbbc1..759706df4721bb6bbc83801b142f4d3141327b20 100644 --- a/skia/include/third_party/vulkan/vulkan/vulkan_core.h +++ b/skia/include/third_party/vulkan/vulkan/vulkan_core.h @@ -368,6 +368,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129003, VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129004, VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID = 1000129005, + VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_OPENHARMONY = 1000452005, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = 1000130000, VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = 1000130001, VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000, diff --git a/skia/src/gpu/vk/GrVkCaps.cpp b/skia/src/gpu/vk/GrVkCaps.cpp index 384448104fd10ad8e669fb7395ebd7ae64acdf5e..84e5e5c5540e54d66cc80a2dcabda23ebcf3bff0 100644 --- a/skia/src/gpu/vk/GrVkCaps.cpp +++ b/skia/src/gpu/vk/GrVkCaps.cpp @@ -1237,11 +1237,31 @@ bool GrVkCaps::isFormatTexturableAndUploadable(GrColorType ct, SkToBool(ctFlags & ColorTypeInfo::kUploadData_Flag); } +#ifdef SK_BUILD_FOR_OPENHARMONY +static bool isExternalBackendFormat(const GrBackendFormat& format) { + const GrVkYcbcrConversionInfo* ycbcrInfo = format.getVkYcbcrConversionInfo(); + SkASSERT(ycbcrInfo); + + // All external formats have a valid ycbcrInfo used for sampling and a non zero external format + if (ycbcrInfo->isValid() && ycbcrInfo->fExternalFormat != 0) { + return true; + } + return false; +} +#endif + bool GrVkCaps::isFormatTexturable(const GrBackendFormat& format) const { VkFormat vkFormat; if (!format.asVkFormat(&vkFormat)) { return false; } +#ifdef SK_BUILD_FOR_OPENHARMONY + if (isExternalBackendFormat(format)) { + // We can always texture from an external format (assuming we have the ycbcr conversion + // info which we require to be passed in.) + return true; + } +#endif return this->isVkFormatTexturable(vkFormat); } diff --git a/skia/src/gpu/vk/GrVkGpu.cpp b/skia/src/gpu/vk/GrVkGpu.cpp index a5b451ade9ccf80a1253bbd3415f271246bbcf53..631bcebf49da0457f3b44043014a39e8deb5271a 100644 --- a/skia/src/gpu/vk/GrVkGpu.cpp +++ b/skia/src/gpu/vk/GrVkGpu.cpp @@ -1150,6 +1150,11 @@ static bool check_image_info(const GrVkCaps& caps, } static bool check_tex_image_info(const GrVkCaps& caps, const GrVkImageInfo& info) { +#ifdef SK_BUILD_FOR_OPENHARMONY + if (info.fYcbcrConversionInfo.isValid() && info.fYcbcrConversionInfo.fExternalFormat != 0) { + return true; + } +#endif if (info.fImageTiling == VK_IMAGE_TILING_OPTIMAL) { if (!caps.isVkFormatTexturable(info.fFormat)) { return false; diff --git a/skia/src/gpu/vk/GrVkSamplerYcbcrConversion.cpp b/skia/src/gpu/vk/GrVkSamplerYcbcrConversion.cpp index f33f5216dc0964cd95ef01f599caceb262be3bbe..8e8aa25a56f83c622a1f1ed0a0d3e3542c890305 100644 --- a/skia/src/gpu/vk/GrVkSamplerYcbcrConversion.cpp +++ b/skia/src/gpu/vk/GrVkSamplerYcbcrConversion.cpp @@ -9,6 +9,11 @@ #include "src/gpu/vk/GrVkGpu.h" +#ifdef SK_BUILD_FOR_OPENHARMONY +#include "vulkan/vulkan_ohos.h" +#include "vulkan/vulkan_core.h" +#endif + GrVkSamplerYcbcrConversion* GrVkSamplerYcbcrConversion::Create( const GrVkGpu* gpu, const GrVkYcbcrConversionInfo& info) { if (!gpu->vkCaps().supportsYcbcrConversion()) { @@ -61,6 +66,14 @@ GrVkSamplerYcbcrConversion* GrVkSamplerYcbcrConversion::Create( externalFormat.externalFormat = info.fExternalFormat; ycbcrCreateInfo.pNext = &externalFormat; } +#elif defined(SK_BUILD_FOR_OPENHARMONY) + VkExternalFormatOpenHarmony externalFormat; + if (info.fExternalFormat) { + externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_OPENHARMONY; + externalFormat.pNext = nullptr; + externalFormat.externalFormat = info.fExternalFormat; + ycbcrCreateInfo.pNext = &externalFormat; + } #else // External images are supported only on Android; SkASSERT(!info.fExternalFormat);