1 // Copyright (c) 2018 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 
5 #include "gpu/vulkan/x/vulkan_implementation_x11.h"
6 
7 #include "base/base_paths.h"
8 #include "base/callback_helpers.h"
9 #include "base/files/file_path.h"
10 #include "base/notreached.h"
11 #include "base/optional.h"
12 #include "base/path_service.h"
13 #include "gpu/vulkan/vulkan_function_pointers.h"
14 #include "gpu/vulkan/vulkan_image.h"
15 #include "gpu/vulkan/vulkan_instance.h"
16 #include "gpu/vulkan/vulkan_surface.h"
17 #include "gpu/vulkan/vulkan_util.h"
18 #include "gpu/vulkan/x/vulkan_surface_x11.h"
19 #include "ui/base/x/x11_util.h"
20 #include "ui/gfx/gpu_fence.h"
21 #include "ui/gfx/gpu_memory_buffer.h"
22 #include "ui/gfx/x/connection.h"
23 
24 namespace gpu {
25 
26 namespace {
27 
InitializeVulkanFunctionPointers(const base::FilePath & path,VulkanFunctionPointers * vulkan_function_pointers)28 bool InitializeVulkanFunctionPointers(
29     const base::FilePath& path,
30     VulkanFunctionPointers* vulkan_function_pointers) {
31   base::NativeLibraryLoadError native_library_load_error;
32   vulkan_function_pointers->vulkan_loader_library =
33       base::LoadNativeLibrary(path, &native_library_load_error);
34   return !!vulkan_function_pointers->vulkan_loader_library;
35 }
36 
37 }  // namespace
38 
VulkanImplementationX11(bool use_swiftshader)39 VulkanImplementationX11::VulkanImplementationX11(bool use_swiftshader)
40     : VulkanImplementation(use_swiftshader) {
41   x11::Connection::Get();
42 }
43 
44 VulkanImplementationX11::~VulkanImplementationX11() = default;
45 
InitializeVulkanInstance(bool using_surface)46 bool VulkanImplementationX11::InitializeVulkanInstance(bool using_surface) {
47   if (using_surface && !use_swiftshader() && !ui::IsVulkanSurfaceSupported())
48     using_surface = false;
49   using_surface_ = using_surface;
50   // Unset DISPLAY env, so the vulkan can be initialized successfully, if the X
51   // server doesn't support Vulkan surface.
52   base::Optional<ui::ScopedUnsetDisplay> unset_display;
53   if (!using_surface_)
54     unset_display.emplace();
55 
56   std::vector<const char*> required_extensions = {
57       VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
58       VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME};
59   if (using_surface_) {
60     required_extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
61     required_extensions.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
62   }
63 
64   VulkanFunctionPointers* vulkan_function_pointers =
65       gpu::GetVulkanFunctionPointers();
66 
67   base::FilePath path;
68   if (use_swiftshader()) {
69     if (!base::PathService::Get(base::DIR_MODULE, &path))
70       return false;
71 
72     path = path.Append("libvk_swiftshader.so");
73   } else {
74     path = base::FilePath("libvulkan.so.1");
75   }
76 
77   if (!InitializeVulkanFunctionPointers(path, vulkan_function_pointers))
78     return false;
79 
80   if (!vulkan_instance_.Initialize(required_extensions, {}))
81     return false;
82   return true;
83 }
84 
GetVulkanInstance()85 VulkanInstance* VulkanImplementationX11::GetVulkanInstance() {
86   return &vulkan_instance_;
87 }
88 
CreateViewSurface(gfx::AcceleratedWidget window)89 std::unique_ptr<VulkanSurface> VulkanImplementationX11::CreateViewSurface(
90     gfx::AcceleratedWidget window) {
91   if (!using_surface_)
92     return nullptr;
93   return VulkanSurfaceX11::Create(vulkan_instance_.vk_instance(),
94                                   static_cast<x11::Window>(window));
95 }
96 
GetPhysicalDevicePresentationSupport(VkPhysicalDevice device,const std::vector<VkQueueFamilyProperties> & queue_family_properties,uint32_t queue_family_index)97 bool VulkanImplementationX11::GetPhysicalDevicePresentationSupport(
98     VkPhysicalDevice device,
99     const std::vector<VkQueueFamilyProperties>& queue_family_properties,
100     uint32_t queue_family_index) {
101   // TODO(samans): Don't early out once Swiftshader supports this method.
102   // https://crbug.com/swiftshader/129
103   if (use_swiftshader())
104     return true;
105   auto* connection = x11::Connection::Get();
106   return vkGetPhysicalDeviceXcbPresentationSupportKHR(
107       device, queue_family_index, connection->XcbConnection(),
108       static_cast<xcb_visualid_t>(connection->default_root_visual().visual_id));
109 }
110 
111 std::vector<const char*>
GetRequiredDeviceExtensions()112 VulkanImplementationX11::GetRequiredDeviceExtensions() {
113   std::vector<const char*> extensions = {};
114   if (using_surface_)
115     extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
116   return extensions;
117 }
118 
119 std::vector<const char*>
GetOptionalDeviceExtensions()120 VulkanImplementationX11::GetOptionalDeviceExtensions() {
121   return {VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
122           VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
123           VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
124           VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,
125           VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME};
126 }
127 
CreateVkFenceForGpuFence(VkDevice vk_device)128 VkFence VulkanImplementationX11::CreateVkFenceForGpuFence(VkDevice vk_device) {
129   NOTREACHED();
130   return VK_NULL_HANDLE;
131 }
132 
ExportVkFenceToGpuFence(VkDevice vk_device,VkFence vk_fence)133 std::unique_ptr<gfx::GpuFence> VulkanImplementationX11::ExportVkFenceToGpuFence(
134     VkDevice vk_device,
135     VkFence vk_fence) {
136   NOTREACHED();
137   return nullptr;
138 }
139 
CreateExternalSemaphore(VkDevice vk_device)140 VkSemaphore VulkanImplementationX11::CreateExternalSemaphore(
141     VkDevice vk_device) {
142   return CreateExternalVkSemaphore(
143       vk_device, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT);
144 }
145 
ImportSemaphoreHandle(VkDevice vk_device,SemaphoreHandle sync_handle)146 VkSemaphore VulkanImplementationX11::ImportSemaphoreHandle(
147     VkDevice vk_device,
148     SemaphoreHandle sync_handle) {
149   return ImportVkSemaphoreHandle(vk_device, std::move(sync_handle));
150 }
151 
GetSemaphoreHandle(VkDevice vk_device,VkSemaphore vk_semaphore)152 SemaphoreHandle VulkanImplementationX11::GetSemaphoreHandle(
153     VkDevice vk_device,
154     VkSemaphore vk_semaphore) {
155   return GetVkSemaphoreHandle(vk_device, vk_semaphore,
156                               VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT);
157 }
158 
159 VkExternalMemoryHandleTypeFlagBits
GetExternalImageHandleType()160 VulkanImplementationX11::GetExternalImageHandleType() {
161   return VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
162 }
163 
CanImportGpuMemoryBuffer(gfx::GpuMemoryBufferType memory_buffer_type)164 bool VulkanImplementationX11::CanImportGpuMemoryBuffer(
165     gfx::GpuMemoryBufferType memory_buffer_type) {
166   return false;
167 }
168 
169 std::unique_ptr<VulkanImage>
CreateImageFromGpuMemoryHandle(VulkanDeviceQueue * device_queue,gfx::GpuMemoryBufferHandle gmb_handle,gfx::Size size,VkFormat vk_formae)170 VulkanImplementationX11::CreateImageFromGpuMemoryHandle(
171     VulkanDeviceQueue* device_queue,
172     gfx::GpuMemoryBufferHandle gmb_handle,
173     gfx::Size size,
174     VkFormat vk_formae) {
175   NOTIMPLEMENTED();
176   return nullptr;
177 }
178 
179 }  // namespace gpu
180