vulkan_image_android.cc 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "gpu/vulkan/vulkan_image.h"
  5. #include "base/android/android_hardware_buffer_compat.h"
  6. #include "base/debug/crash_logging.h"
  7. #include "base/logging.h"
  8. #include "gpu/vulkan/vulkan_device_queue.h"
  9. #include "gpu/vulkan/vulkan_function_pointers.h"
  10. namespace gpu {
  11. namespace {
  12. bool IsSinglePlaneRGBVulkanAHBFormat(VkFormat format) {
  13. switch (format) {
  14. // AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM
  15. case VK_FORMAT_R8G8B8A8_UNORM:
  16. // AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM
  17. case VK_FORMAT_R8G8B8_UNORM:
  18. // AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM
  19. case VK_FORMAT_R5G6B5_UNORM_PACK16:
  20. // AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT
  21. case VK_FORMAT_R16G16B16A16_SFLOAT:
  22. // AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM
  23. case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
  24. return true;
  25. default:
  26. return false;
  27. }
  28. }
  29. } // namespace
  30. bool VulkanImage::InitializeFromGpuMemoryBufferHandle(
  31. VulkanDeviceQueue* device_queue,
  32. gfx::GpuMemoryBufferHandle gmb_handle,
  33. const gfx::Size& size,
  34. VkFormat format,
  35. VkImageUsageFlags usage,
  36. VkImageCreateFlags flags,
  37. VkImageTiling image_tiling,
  38. uint32_t queue_family_index) {
  39. if (gmb_handle.type != gfx::GpuMemoryBufferType::ANDROID_HARDWARE_BUFFER) {
  40. DLOG(ERROR) << "gmb_handle.type is not supported. type:" << gmb_handle.type;
  41. return false;
  42. }
  43. DCHECK(gmb_handle.android_hardware_buffer.is_valid());
  44. SCOPED_CRASH_KEY_BOOL("vulkan", "gmb_buffer.is_valid",
  45. gmb_handle.android_hardware_buffer.is_valid());
  46. auto& ahb_handle = gmb_handle.android_hardware_buffer;
  47. // To obtain format properties of an Android hardware buffer, include an
  48. // instance of VkAndroidHardwareBufferFormatPropertiesANDROID in the pNext
  49. // chain of the VkAndroidHardwareBufferPropertiesANDROID instance passed to
  50. // vkGetAndroidHardwareBufferPropertiesANDROID.
  51. VkAndroidHardwareBufferFormatPropertiesANDROID ahb_format_props = {
  52. VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
  53. };
  54. VkAndroidHardwareBufferPropertiesANDROID ahb_props = {
  55. .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
  56. .pNext = &ahb_format_props,
  57. };
  58. VkDevice vk_device = device_queue->GetVulkanDevice();
  59. VkResult result = vkGetAndroidHardwareBufferPropertiesANDROID(
  60. vk_device, ahb_handle.get(), &ahb_props);
  61. if (result != VK_SUCCESS) {
  62. LOG(ERROR)
  63. << "GetAhbProps: vkGetAndroidHardwareBufferPropertiesANDROID failed : "
  64. << result;
  65. return false;
  66. }
  67. // To create an image with an external format, include an instance of
  68. // VkExternalFormatANDROID in the pNext chain of VkImageCreateInfo.
  69. VkExternalFormatANDROID external_format = {
  70. .sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID,
  71. // If externalFormat is zero, the effect is as if the
  72. // VkExternalFormatANDROID structure was not present. Otherwise, the image
  73. // will have the specified external format.
  74. .externalFormat = 0,
  75. };
  76. const bool should_use_external_format =
  77. !IsSinglePlaneRGBVulkanAHBFormat(ahb_format_props.format);
  78. if (should_use_external_format) {
  79. // externalFormat must be 0 or a value returned in the externalFormat member
  80. // of VkAndroidHardwareBufferFormatPropertiesANDROID by an earlier call to
  81. // vkGetAndroidHardwareBufferPropertiesANDROID.
  82. external_format.externalFormat = ahb_format_props.externalFormat;
  83. }
  84. // To define a set of external memory handle types that may be used as backing
  85. // store for an image, add a VkExternalMemoryImageCreateInfo structure to the
  86. // pNext chain of the VkImageCreateInfo structure.
  87. VkExternalMemoryImageCreateInfo external_memory_image_info = {
  88. .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
  89. .pNext = &external_format,
  90. .handleTypes =
  91. VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
  92. };
  93. // Get the AHB description.
  94. AHardwareBuffer_Desc ahb_desc = {};
  95. base::AndroidHardwareBufferCompat::GetInstance().Describe(ahb_handle.get(),
  96. &ahb_desc);
  97. // Intended usage of the image.
  98. VkImageUsageFlags usage_flags = 0;
  99. // Get Vulkan Image usage flag equivalence of AHB usage.
  100. if (ahb_desc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) {
  101. usage_flags = usage_flags | VK_IMAGE_USAGE_SAMPLED_BIT |
  102. VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
  103. }
  104. if (ahb_desc.usage & AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT) {
  105. usage_flags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
  106. }
  107. // TODO(vikassoni) : AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP is supported from API
  108. // level 28 which is not part of current android_ndk version in chromium. Add
  109. // equivalent VK usage later.
  110. if (!usage_flags) {
  111. LOG(ERROR) << "No valid usage flags found";
  112. return false;
  113. }
  114. // Skia currently requires all wrapped VkImages to have transfer src and dst
  115. // usage. Additionally all AHB support these usages when imported into vulkan.
  116. usage_flags |=
  117. VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
  118. VkImageCreateFlags create_flags = 0;
  119. if (ahb_desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) {
  120. create_flags = VK_IMAGE_CREATE_PROTECTED_BIT;
  121. }
  122. // To import memory created outside of the current Vulkan instance from an
  123. // Android hardware buffer, add a VkImportAndroidHardwareBufferInfoANDROID
  124. // structure to the pNext chain of the VkMemoryAllocateInfo structure.
  125. VkImportAndroidHardwareBufferInfoANDROID ahb_import_info = {
  126. .sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID,
  127. .buffer = ahb_handle.get(),
  128. };
  129. VkMemoryRequirements requirements = {
  130. .size = ahb_props.allocationSize,
  131. .memoryTypeBits = ahb_props.memoryTypeBits,
  132. };
  133. // If we want to use external format, format must be VK_FORMAT_UNDEFINED.
  134. if (!Initialize(device_queue, size,
  135. should_use_external_format ? VK_FORMAT_UNDEFINED
  136. : ahb_format_props.format,
  137. usage_flags, create_flags, VK_IMAGE_TILING_OPTIMAL,
  138. &external_memory_image_info, &ahb_import_info,
  139. &requirements)) {
  140. return false;
  141. }
  142. queue_family_index_ = queue_family_index;
  143. if (should_use_external_format) {
  144. ycbcr_info_.emplace(VK_FORMAT_UNDEFINED, ahb_format_props.externalFormat,
  145. ahb_format_props.suggestedYcbcrModel,
  146. ahb_format_props.suggestedYcbcrRange,
  147. ahb_format_props.suggestedXChromaOffset,
  148. ahb_format_props.suggestedYChromaOffset,
  149. ahb_format_props.formatFeatures);
  150. }
  151. return true;
  152. }
  153. } // namespace gpu