| // 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 "impeller/renderer/backend/vulkan/swapchain_details_vk.h" |
| |
| #include "impeller/base/validation.h" |
| |
| namespace impeller { |
| |
| std::unique_ptr<SwapchainDetailsVK> SwapchainDetailsVK::Create( |
| vk::PhysicalDevice physical_device, |
| vk::SurfaceKHR surface) { |
| FML_DCHECK(surface) << "surface provided as nullptr"; |
| |
| auto capabilities_res = physical_device.getSurfaceCapabilitiesKHR(surface); |
| if (capabilities_res.result != vk::Result::eSuccess) { |
| VALIDATION_LOG << "Failed to get surface capabilities: " |
| << vk::to_string(capabilities_res.result); |
| return nullptr; |
| } |
| vk::SurfaceCapabilitiesKHR capabilities = capabilities_res.value; |
| |
| auto surface_formats_res = physical_device.getSurfaceFormatsKHR(surface); |
| if (surface_formats_res.result != vk::Result::eSuccess) { |
| VALIDATION_LOG << "Failed to get surface formats: " |
| << vk::to_string(surface_formats_res.result); |
| return nullptr; |
| } |
| std::vector<vk::SurfaceFormatKHR> surface_formats = surface_formats_res.value; |
| |
| auto surface_present_modes_res = |
| physical_device.getSurfacePresentModesKHR(surface); |
| if (surface_present_modes_res.result != vk::Result::eSuccess) { |
| VALIDATION_LOG << "Failed to get surface present modes: " |
| << vk::to_string(surface_present_modes_res.result); |
| return nullptr; |
| } |
| std::vector<vk::PresentModeKHR> surface_present_modes = |
| surface_present_modes_res.value; |
| |
| const auto composite_alphas = capabilities.supportedCompositeAlpha; |
| vk::CompositeAlphaFlagBitsKHR composite_alpha; |
| if (composite_alphas & vk::CompositeAlphaFlagBitsKHR::eOpaque) { |
| composite_alpha = vk::CompositeAlphaFlagBitsKHR::eOpaque; |
| } else if (composite_alphas & vk::CompositeAlphaFlagBitsKHR::eInherit) { |
| composite_alpha = vk::CompositeAlphaFlagBitsKHR::eInherit; |
| } else { |
| VALIDATION_LOG << "No supported composite alpha found."; |
| return nullptr; |
| } |
| |
| return std::make_unique<SwapchainDetailsVK>( |
| capabilities, surface_formats, surface_present_modes, composite_alpha); |
| } |
| |
| vk::SurfaceFormatKHR SwapchainDetailsVK::PickSurfaceFormat() const { |
| for (const auto& format : surface_formats_) { |
| if ((format.format == vk::Format::eR8G8B8A8Unorm || |
| format.format == vk::Format::eB8G8R8A8Unorm) && |
| format.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) { |
| return format; |
| } |
| } |
| |
| VALIDATION_LOG << "Picking a sub-optimal surface format."; |
| return surface_formats_[0]; |
| } |
| |
| vk::PresentModeKHR SwapchainDetailsVK::PickPresentationMode() const { |
| for (const auto& mode : present_modes_) { |
| if (mode == vk::PresentModeKHR::eMailbox) { |
| return mode; |
| } |
| } |
| |
| VALIDATION_LOG << "Picking a sub-optimal presentation mode."; |
| // Vulkan spec dictates that FIFO is always available. |
| return vk::PresentModeKHR::eFifo; |
| } |
| |
| vk::CompositeAlphaFlagBitsKHR SwapchainDetailsVK::PickCompositeAlpha() const { |
| return composite_alpha_; |
| } |
| |
| vk::Extent2D SwapchainDetailsVK::PickExtent() const { |
| if (surface_capabilities_.currentExtent.width != |
| std::numeric_limits<uint32_t>::max()) { |
| return surface_capabilities_.currentExtent; |
| } |
| |
| vk::Extent2D actual_extent = { |
| std::max(surface_capabilities_.minImageExtent.width, |
| std::min(surface_capabilities_.maxImageExtent.width, |
| surface_capabilities_.currentExtent.width)), |
| std::max(surface_capabilities_.minImageExtent.height, |
| std::min(surface_capabilities_.maxImageExtent.height, |
| surface_capabilities_.currentExtent.height))}; |
| return actual_extent; |
| } |
| |
| uint32_t SwapchainDetailsVK::GetImageCount() const { |
| uint32_t image_count = surface_capabilities_.minImageCount; |
| // for triple buffering |
| return image_count + 1; |
| } |
| |
| vk::SurfaceTransformFlagBitsKHR SwapchainDetailsVK::GetTransform() const { |
| return surface_capabilities_.currentTransform; |
| } |
| |
| SwapchainDetailsVK::SwapchainDetailsVK( |
| vk::SurfaceCapabilitiesKHR capabilities, |
| std::vector<vk::SurfaceFormatKHR> surface_formats, |
| std::vector<vk::PresentModeKHR> surface_present_modes, |
| vk::CompositeAlphaFlagBitsKHR composite_alpha) |
| : surface_capabilities_(capabilities), |
| surface_formats_(std::move(surface_formats)), |
| present_modes_(std::move(surface_present_modes)), |
| composite_alpha_(composite_alpha) {} |
| |
| SwapchainDetailsVK::~SwapchainDetailsVK() = default; |
| |
| } // namespace impeller |