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