Index: gpu/vulkan/vulkan_surface.cc |
diff --git a/gpu/vulkan/vulkan_surface.cc b/gpu/vulkan/vulkan_surface.cc |
index 158ab4a3a49aaff156443f1ed112edd5668804d4..344045af90cdd14152e79ae1c74fc13587031306 100644 |
--- a/gpu/vulkan/vulkan_surface.cc |
+++ b/gpu/vulkan/vulkan_surface.cc |
@@ -4,11 +4,130 @@ |
#include "gpu/vulkan/vulkan_surface.h" |
+#include <vulkan/vulkan.h> |
+ |
+#include "base/macros.h" |
+#include "gpu/vulkan/vulkan_command_buffer.h" |
#include "gpu/vulkan/vulkan_implementation.h" |
+#include "gpu/vulkan/vulkan_platform.h" |
+#include "gpu/vulkan/vulkan_swap_chain.h" |
+ |
+#if defined(USE_X11) |
+#include "ui/gfx/x/x11_types.h" |
+#endif // defined(USE_X11) |
namespace gpu { |
-VulkanSurface::VulkanSurface() {} |
+namespace { |
+const VkFormat kNativeVkFormat[] = { |
+ VK_FORMAT_B8G8R8A8_UNORM, // FORMAT_BGRA8888, |
+ VK_FORMAT_R5G6B5_UNORM_PACK16, // FORMAT_RGB565, |
+}; |
+static_assert(arraysize(kNativeVkFormat) == VulkanSurface::NUM_SURFACE_FORMATS, |
+ "Array size for kNativeVkFormat must match surface formats."); |
+ |
+} // namespace |
+ |
+class VulkanWSISurface : public VulkanSurface { |
+ public: |
+ explicit VulkanWSISurface(gfx::AcceleratedWidget window) : window_(window) {} |
+ |
+ ~VulkanWSISurface() override { |
+ DCHECK_EQ(static_cast<VkSurfaceKHR>(VK_NULL_HANDLE), surface_); |
+ } |
+ |
+ bool Initialize(VulkanSurface::Format format) override { |
+ DCHECK(format >= 0 && format < NUM_SURFACE_FORMATS); |
+#if defined(VK_USE_PLATFORM_XLIB_KHR) |
+ VkXlibSurfaceCreateInfoKHR surface_create_info = {}; |
+ surface_create_info.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; |
+ surface_create_info.dpy = gfx::GetXDisplay(); |
+ surface_create_info.window = window_; |
+ vkCreateXlibSurfaceKHR(GetVulkanInstance(), &surface_create_info, nullptr, |
+ &surface_); |
+#else |
+#error Unsupported Vulkan Platform. |
+#endif |
+ |
+ // Get list of supported formats. |
+ uint32_t format_count = 0; |
+ VkResult result = vkGetPhysicalDeviceSurfaceFormatsKHR( |
+ GetVulkanPhysicalDevice(), surface_, &format_count, nullptr); |
+ if (VK_SUCCESS != result) { |
+ DLOG(ERROR) << "vkGetPhysicalDeviceSurfaceFormatsKHR() failed: " |
+ << result; |
+ return false; |
+ } |
+ |
+ std::vector<VkSurfaceFormatKHR> formats(format_count); |
+ result = vkGetPhysicalDeviceSurfaceFormatsKHR( |
+ GetVulkanPhysicalDevice(), surface_, &format_count, formats.data()); |
+ if (VK_SUCCESS != result) { |
+ DLOG(ERROR) << "vkGetPhysicalDeviceSurfaceFormatsKHR() failed: " |
+ << result; |
+ return false; |
+ } |
+ |
+ const VkFormat preferred_format = kNativeVkFormat[format]; |
+ if (formats.size() == 1 && VK_FORMAT_UNDEFINED == formats[0].format) { |
+ surface_format_.format = preferred_format; |
+ surface_format_.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; |
+ } else { |
+ bool format_set = false; |
+ for (VkSurfaceFormatKHR supported_format : formats) { |
+ if (supported_format.format == preferred_format) { |
+ surface_format_ = supported_format; |
+ surface_format_.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; |
+ format_set = true; |
+ break; |
+ } |
+ } |
+ if (!format_set) { |
+ DLOG(ERROR) << "Format not supported."; |
+ return false; |
+ } |
+ } |
+ |
+ // Get Surface Information. |
+ VkSurfaceCapabilitiesKHR surface_caps; |
+ result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR( |
+ GetVulkanPhysicalDevice(), surface_, &surface_caps); |
+ if (VK_SUCCESS != result) { |
+ DLOG(ERROR) << "vkGetPhysicalDeviceSurfaceCapabilitiesKHR() failed: " |
+ << result; |
+ return false; |
+ } |
+ |
+ // These are actual surfaces so the current extent should be defined. |
+ DCHECK_NE(UINT_MAX, surface_caps.currentExtent.width); |
+ DCHECK_NE(UINT_MAX, surface_caps.currentExtent.height); |
+ size_ = gfx::Size(surface_caps.currentExtent.width, |
+ surface_caps.currentExtent.height); |
+ |
+ // Create Swapchain. |
+ if (!swap_chain_.Initialize(surface_, surface_caps, surface_format_)) |
+ return false; |
+ |
+ return true; |
+ } |
+ |
+ void Destroy() override { |
+ swap_chain_.Destroy(); |
+ vkDestroySurfaceKHR(GetVulkanInstance(), surface_, nullptr); |
+ surface_ = VK_NULL_HANDLE; |
+ } |
+ |
+ gfx::SwapResult SwapBuffers() override { return swap_chain_.SwapBuffers(); } |
+ VulkanSwapChain* GetSwapChain() override { return &swap_chain_; } |
+ void Finish() override { vkQueueWaitIdle(GetVulkanQueue()); } |
+ |
+ protected: |
+ gfx::AcceleratedWidget window_; |
+ gfx::Size size_; |
+ VkSurfaceKHR surface_ = VK_NULL_HANDLE; |
+ VkSurfaceFormatKHR surface_format_ = {}; |
+ VulkanSwapChain swap_chain_; |
+}; |
// static |
bool VulkanSurface::InitializeOneOff() { |
@@ -20,4 +139,12 @@ bool VulkanSurface::InitializeOneOff() { |
VulkanSurface::~VulkanSurface() {} |
+// static |
+scoped_ptr<VulkanSurface> VulkanSurface::CreateViewSurface( |
+ gfx::AcceleratedWidget window) { |
+ return scoped_ptr<VulkanSurface>(new VulkanWSISurface(window)); |
+} |
+ |
+VulkanSurface::VulkanSurface() {} |
+ |
} // namespace gpu |