vulkan_surface.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. // Copyright (c) 2016 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_surface.h"
  5. #include <vulkan/vulkan.h>
  6. #include <algorithm>
  7. #include "base/logging.h"
  8. #include "base/threading/scoped_blocking_call.h"
  9. #include "base/threading/thread_task_runner_handle.h"
  10. #include "build/build_config.h"
  11. #include "gpu/vulkan/vulkan_device_queue.h"
  12. #include "gpu/vulkan/vulkan_function_pointers.h"
  13. #include "gpu/vulkan/vulkan_swap_chain.h"
  14. #if BUILDFLAG(IS_ANDROID)
  15. #include <android/native_window_jni.h>
  16. #endif
  17. namespace gpu {
  18. namespace {
  19. const VkFormat kPreferredVkFormats32[] = {
  20. VK_FORMAT_B8G8R8A8_UNORM, // FORMAT_BGRA8888,
  21. VK_FORMAT_R8G8B8A8_UNORM, // FORMAT_RGBA8888,
  22. };
  23. const VkFormat kPreferredVkFormats16[] = {
  24. VK_FORMAT_R5G6B5_UNORM_PACK16, // FORMAT_RGB565,
  25. };
  26. VkSurfaceTransformFlagBitsKHR ToVkSurfaceTransformFlag(
  27. gfx::OverlayTransform transform) {
  28. switch (transform) {
  29. case gfx::OVERLAY_TRANSFORM_NONE:
  30. return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
  31. case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL:
  32. return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR;
  33. case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
  34. return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR;
  35. case gfx::OVERLAY_TRANSFORM_ROTATE_90:
  36. return VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR;
  37. case gfx::OVERLAY_TRANSFORM_ROTATE_180:
  38. return VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR;
  39. case gfx::OVERLAY_TRANSFORM_ROTATE_270:
  40. return VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR;
  41. default:
  42. NOTREACHED() << "transform:" << transform;
  43. return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
  44. };
  45. }
  46. gfx::OverlayTransform FromVkSurfaceTransformFlag(
  47. VkSurfaceTransformFlagBitsKHR transform) {
  48. switch (transform) {
  49. case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
  50. return gfx::OVERLAY_TRANSFORM_NONE;
  51. case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
  52. return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
  53. case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
  54. return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
  55. case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
  56. return gfx::OVERLAY_TRANSFORM_ROTATE_90;
  57. case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
  58. return gfx::OVERLAY_TRANSFORM_ROTATE_180;
  59. case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
  60. return gfx::OVERLAY_TRANSFORM_ROTATE_270;
  61. default:
  62. NOTREACHED() << "transform:" << transform;
  63. return gfx::OVERLAY_TRANSFORM_INVALID;
  64. }
  65. }
  66. // Minimum VkImages in a vulkan swap chain.
  67. uint32_t kMinImageCount = 3u;
  68. } // namespace
  69. VulkanSurface::~VulkanSurface() {
  70. DCHECK_EQ(static_cast<VkSurfaceKHR>(VK_NULL_HANDLE), surface_);
  71. #if BUILDFLAG(IS_ANDROID)
  72. if (accelerated_widget_)
  73. ANativeWindow_release(accelerated_widget_);
  74. #endif
  75. }
  76. VulkanSurface::VulkanSurface(VkInstance vk_instance,
  77. gfx::AcceleratedWidget accelerated_widget,
  78. VkSurfaceKHR surface,
  79. uint64_t acquire_next_image_timeout_ns,
  80. std::unique_ptr<gfx::VSyncProvider> vsync_provider)
  81. : vk_instance_(vk_instance),
  82. accelerated_widget_(accelerated_widget),
  83. surface_(surface),
  84. acquire_next_image_timeout_ns_(acquire_next_image_timeout_ns),
  85. vsync_provider_(std::move(vsync_provider)) {
  86. DCHECK_NE(static_cast<VkSurfaceKHR>(VK_NULL_HANDLE), surface_);
  87. if (!vsync_provider_) {
  88. vsync_provider_ = std::make_unique<gfx::FixedVSyncProvider>(
  89. base::TimeTicks(), base::Seconds(1) / 60);
  90. }
  91. #if BUILDFLAG(IS_ANDROID)
  92. if (accelerated_widget_)
  93. ANativeWindow_acquire(accelerated_widget_);
  94. #endif
  95. }
  96. bool VulkanSurface::Initialize(VulkanDeviceQueue* device_queue,
  97. VulkanSurface::Format format) {
  98. DCHECK(format >= 0 && format < NUM_SURFACE_FORMATS);
  99. DCHECK(device_queue);
  100. device_queue_ = device_queue;
  101. VkBool32 present_support;
  102. VkResult result = vkGetPhysicalDeviceSurfaceSupportKHR(
  103. device_queue_->GetVulkanPhysicalDevice(),
  104. device_queue_->GetVulkanQueueIndex(), surface_, &present_support);
  105. if (result != VK_SUCCESS) {
  106. DLOG(ERROR) << "vkGetPhysicalDeviceSurfaceSupportKHR() failed: " << result;
  107. return false;
  108. }
  109. if (!present_support) {
  110. DLOG(ERROR) << "Surface not supported by present queue.";
  111. return false;
  112. }
  113. // Get list of supported formats.
  114. uint32_t format_count = 0;
  115. result = vkGetPhysicalDeviceSurfaceFormatsKHR(
  116. device_queue_->GetVulkanPhysicalDevice(), surface_, &format_count,
  117. nullptr);
  118. if (VK_SUCCESS != result) {
  119. DLOG(ERROR) << "vkGetPhysicalDeviceSurfaceFormatsKHR() failed: " << result;
  120. return false;
  121. }
  122. std::vector<VkSurfaceFormatKHR> formats(format_count);
  123. result = vkGetPhysicalDeviceSurfaceFormatsKHR(
  124. device_queue_->GetVulkanPhysicalDevice(), surface_, &format_count,
  125. formats.data());
  126. if (VK_SUCCESS != result) {
  127. DLOG(ERROR) << "vkGetPhysicalDeviceSurfaceFormatsKHR() failed: " << result;
  128. return false;
  129. }
  130. const VkFormat* preferred_formats = (format == FORMAT_RGBA_32)
  131. ? kPreferredVkFormats32
  132. : kPreferredVkFormats16;
  133. unsigned int size = (format == FORMAT_RGBA_32)
  134. ? std::size(kPreferredVkFormats32)
  135. : std::size(kPreferredVkFormats16);
  136. if (formats.size() == 1 && VK_FORMAT_UNDEFINED == formats[0].format) {
  137. surface_format_.format = preferred_formats[0];
  138. surface_format_.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
  139. } else {
  140. bool format_set = false;
  141. for (VkSurfaceFormatKHR supported_format : formats) {
  142. unsigned int counter = 0;
  143. while (counter < size && format_set == false) {
  144. if (supported_format.format == preferred_formats[counter]) {
  145. surface_format_ = supported_format;
  146. surface_format_.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
  147. format_set = true;
  148. }
  149. counter++;
  150. }
  151. if (format_set)
  152. break;
  153. }
  154. if (!format_set) {
  155. DLOG(ERROR) << "Format not supported.";
  156. return false;
  157. }
  158. }
  159. VkSurfaceCapabilitiesKHR surface_caps;
  160. result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
  161. device_queue_->GetVulkanPhysicalDevice(), surface_, &surface_caps);
  162. if (VK_SUCCESS != result) {
  163. DLOG(ERROR) << "vkGetPhysicalDeviceSurfaceCapabilitiesKHR() failed: "
  164. << result;
  165. return false;
  166. }
  167. constexpr auto kRequiredUsageFlags =
  168. VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
  169. constexpr auto kOptionalUsageFlags =
  170. VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
  171. if ((surface_caps.supportedUsageFlags & kRequiredUsageFlags) !=
  172. kRequiredUsageFlags) {
  173. DLOG(ERROR) << "Vulkan surface doesn't support necessary usage. "
  174. "supportedUsageFlags: 0x"
  175. << std::hex << surface_caps.supportedUsageFlags;
  176. }
  177. image_usage_flags_ = (kRequiredUsageFlags | kOptionalUsageFlags) &
  178. surface_caps.supportedUsageFlags;
  179. return true;
  180. }
  181. void VulkanSurface::Destroy() {
  182. if (swap_chain_) {
  183. swap_chain_->Destroy();
  184. swap_chain_ = nullptr;
  185. }
  186. vkDestroySurfaceKHR(vk_instance_, surface_, nullptr);
  187. surface_ = VK_NULL_HANDLE;
  188. }
  189. gfx::SwapResult VulkanSurface::SwapBuffers(
  190. PresentationCallback presentation_callback) {
  191. return PostSubBuffer(gfx::Rect(image_size_),
  192. std::move(presentation_callback));
  193. }
  194. gfx::SwapResult VulkanSurface::PostSubBuffer(
  195. const gfx::Rect& rect,
  196. PresentationCallback presentation_callback) {
  197. auto result = swap_chain_->PostSubBuffer(rect);
  198. PostSubBufferCompleted({}, std::move(presentation_callback), result);
  199. return result;
  200. }
  201. void VulkanSurface::PostSubBufferAsync(
  202. const gfx::Rect& rect,
  203. VulkanSwapChain::PostSubBufferCompletionCallback completion_callback,
  204. PresentationCallback presentation_callback) {
  205. completion_callback = base::BindOnce(
  206. &VulkanSurface::PostSubBufferCompleted, weak_ptr_factory_.GetWeakPtr(),
  207. std::move(completion_callback), std::move(presentation_callback));
  208. swap_chain_->PostSubBufferAsync(rect, std::move(completion_callback));
  209. }
  210. void VulkanSurface::Finish() {
  211. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  212. base::BlockingType::WILL_BLOCK);
  213. vkQueueWaitIdle(device_queue_->GetVulkanQueue());
  214. }
  215. bool VulkanSurface::Reshape(const gfx::Size& size,
  216. gfx::OverlayTransform transform) {
  217. return CreateSwapChain(size, transform);
  218. }
  219. base::TimeDelta VulkanSurface::GetDisplayRefreshInterval() {
  220. DCHECK(vsync_provider_->SupportGetVSyncParametersIfAvailable());
  221. base::TimeTicks timestamp;
  222. base::TimeDelta interval;
  223. vsync_provider_->GetVSyncParametersIfAvailable(&timestamp, &interval);
  224. return interval;
  225. }
  226. bool VulkanSurface::CreateSwapChain(const gfx::Size& size,
  227. gfx::OverlayTransform transform) {
  228. // Get Surface Information.
  229. VkSurfaceCapabilitiesKHR surface_caps;
  230. VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
  231. device_queue_->GetVulkanPhysicalDevice(), surface_, &surface_caps);
  232. if (VK_SUCCESS != result) {
  233. LOG(FATAL) << "vkGetPhysicalDeviceSurfaceCapabilitiesKHR() failed: "
  234. << result;
  235. return false;
  236. }
  237. auto vk_transform = transform != gfx::OVERLAY_TRANSFORM_INVALID
  238. ? ToVkSurfaceTransformFlag(transform)
  239. : surface_caps.currentTransform;
  240. DCHECK(vk_transform == (vk_transform & surface_caps.supportedTransforms));
  241. if (transform == gfx::OVERLAY_TRANSFORM_INVALID)
  242. transform = FromVkSurfaceTransformFlag(surface_caps.currentTransform);
  243. // For Android, the current vulkan surface size may not match the new size
  244. // (the current window size), in that case, we will create a swap chain with
  245. // the requested new size, and vulkan surface size should match the swapchain
  246. // images size soon.
  247. gfx::Size image_size = size;
  248. if (image_size.IsEmpty()) {
  249. // If width and height of the surface are 0xFFFFFFFF, it means the surface
  250. // size will be determined by the extent of a swapchain targeting the
  251. // surface. In that case, we will use the minImageExtent for the swapchain.
  252. const uint32_t kUndefinedExtent = 0xFFFFFFFF;
  253. if (surface_caps.currentExtent.width == kUndefinedExtent &&
  254. surface_caps.currentExtent.height == kUndefinedExtent) {
  255. image_size.SetSize(surface_caps.minImageExtent.width,
  256. surface_caps.minImageExtent.height);
  257. } else {
  258. image_size.SetSize(surface_caps.currentExtent.width,
  259. surface_caps.currentExtent.height);
  260. }
  261. if (transform == gfx::OVERLAY_TRANSFORM_ROTATE_90 ||
  262. transform == gfx::OVERLAY_TRANSFORM_ROTATE_270) {
  263. image_size.SetSize(image_size.height(), image_size.width());
  264. }
  265. }
  266. DCHECK_GE(static_cast<uint32_t>(image_size.width()),
  267. surface_caps.minImageExtent.width);
  268. DCHECK_GE(static_cast<uint32_t>(image_size.height()),
  269. surface_caps.minImageExtent.height);
  270. DCHECK_LE(static_cast<uint32_t>(image_size.width()),
  271. surface_caps.maxImageExtent.width);
  272. DCHECK_LE(static_cast<uint32_t>(image_size.height()),
  273. surface_caps.maxImageExtent.height);
  274. DCHECK_GT(static_cast<uint32_t>(image_size.width()), 0u);
  275. DCHECK_GT(static_cast<uint32_t>(image_size.height()), 0u);
  276. if (image_size_ == image_size && transform_ == transform &&
  277. swap_chain_->state() == VK_SUCCESS) {
  278. return true;
  279. }
  280. image_size_ = image_size;
  281. transform_ = transform;
  282. const VkCompositeAlphaFlagBitsKHR kCompositeAlphaBits[] = {
  283. VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
  284. VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR,
  285. VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR,
  286. VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,
  287. };
  288. for (auto composite_alpha_bit : kCompositeAlphaBits) {
  289. if (surface_caps.supportedCompositeAlpha & composite_alpha_bit) {
  290. composite_alpha_ = composite_alpha_bit;
  291. break;
  292. }
  293. }
  294. auto swap_chain =
  295. std::make_unique<VulkanSwapChain>(acquire_next_image_timeout_ns_);
  296. // Create swap chain.
  297. auto min_image_count = std::max(surface_caps.minImageCount, kMinImageCount);
  298. if (!swap_chain->Initialize(device_queue_, surface_, surface_format_,
  299. image_size_, min_image_count, image_usage_flags_,
  300. vk_transform, composite_alpha_,
  301. std::move(swap_chain_))) {
  302. return false;
  303. }
  304. swap_chain_ = std::move(swap_chain);
  305. ++swap_chain_generation_;
  306. return true;
  307. }
  308. void VulkanSurface::PostSubBufferCompleted(
  309. VulkanSwapChain::PostSubBufferCompletionCallback completion_callback,
  310. PresentationCallback presentation_callback,
  311. gfx::SwapResult result) {
  312. if (completion_callback)
  313. std::move(completion_callback).Run(result);
  314. gfx::PresentationFeedback feedback;
  315. if (result == gfx::SwapResult::SWAP_FAILED) {
  316. feedback = gfx::PresentationFeedback::Failure();
  317. } else {
  318. DCHECK(vsync_provider_->SupportGetVSyncParametersIfAvailable());
  319. base::TimeTicks timestamp;
  320. base::TimeDelta interval;
  321. vsync_provider_->GetVSyncParametersIfAvailable(&timestamp, &interval);
  322. if (timestamp.is_null())
  323. timestamp = base::TimeTicks::Now();
  324. feedback = gfx::PresentationFeedback(timestamp, interval, /*flags=*/0);
  325. }
  326. if (base::ThreadTaskRunnerHandle::IsSet()) {
  327. base::ThreadTaskRunnerHandle::Get()->PostTask(
  328. FROM_HERE, base::BindOnce(std::move(presentation_callback), feedback));
  329. } else {
  330. // For webview_instrumentation_test, ThreadTaskRunnerHandle is not set, so
  331. // we have to call the callback directly.
  332. std::move(presentation_callback).Run(feedback);
  333. }
  334. }
  335. } // namespace gpu