xref: /aosp_15_r20/external/skia/tools/window/unix/GraphiteNativeVulkanWindowContext_unix.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2023 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 #include "tools/window/unix/GraphiteNativeVulkanWindowContext_unix.h"
8 
9 #include "tools/gpu/vk/VkTestUtils.h"
10 #include "tools/window/GraphiteNativeVulkanWindowContext.h"
11 #include "tools/window/unix/XlibWindowInfo.h"
12 
13 #include <X11/Xlib-xcb.h>
14 
15 namespace skwindow {
16 
MakeGraphiteNativeVulkanForXlib(const XlibWindowInfo & info,std::unique_ptr<const DisplayParams> displayParams)17 std::unique_ptr<WindowContext> MakeGraphiteNativeVulkanForXlib(
18         const XlibWindowInfo& info, std::unique_ptr<const DisplayParams> displayParams) {
19     PFN_vkGetInstanceProcAddr instProc;
20     if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc)) {
21         SkDebugf("Could not load vulkan library\n");
22         return nullptr;
23     }
24 
25     auto createVkSurface = [&info, instProc](VkInstance instance) -> VkSurfaceKHR {
26         static PFN_vkCreateXcbSurfaceKHR createXcbSurfaceKHR = nullptr;
27         if (!createXcbSurfaceKHR) {
28             createXcbSurfaceKHR =
29                     (PFN_vkCreateXcbSurfaceKHR)instProc(instance, "vkCreateXcbSurfaceKHR");
30         }
31 
32         VkSurfaceKHR surface;
33 
34         VkXcbSurfaceCreateInfoKHR surfaceCreateInfo;
35         memset(&surfaceCreateInfo, 0, sizeof(VkXcbSurfaceCreateInfoKHR));
36         surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
37         surfaceCreateInfo.pNext = nullptr;
38         surfaceCreateInfo.flags = 0;
39         surfaceCreateInfo.connection = XGetXCBConnection(info.fDisplay);
40         surfaceCreateInfo.window = info.fWindow;
41 
42         VkResult res = createXcbSurfaceKHR(instance, &surfaceCreateInfo, nullptr, &surface);
43         if (res != VK_SUCCESS) {
44             return VK_NULL_HANDLE;
45         }
46 
47         return surface;
48     };
49 
50     auto canPresent = [&info, instProc](VkInstance instance,
51                                         VkPhysicalDevice physDev,
52                                         uint32_t queueFamilyIndex) {
53         static PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR
54                 getPhysicalDeviceXcbPresentationSupportKHR = nullptr;
55         if (!getPhysicalDeviceXcbPresentationSupportKHR) {
56             getPhysicalDeviceXcbPresentationSupportKHR =
57                     (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)instProc(
58                             instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
59         }
60 
61         Display* display = info.fDisplay;
62         VisualID visualID =
63                 XVisualIDFromVisual(DefaultVisual(info.fDisplay, DefaultScreen(info.fDisplay)));
64         VkBool32 check = getPhysicalDeviceXcbPresentationSupportKHR(
65                 physDev, queueFamilyIndex, XGetXCBConnection(display), visualID);
66         return (check != VK_FALSE);
67     };
68     std::unique_ptr<WindowContext> ctx(new internal::GraphiteVulkanWindowContext(
69             std::move(displayParams), createVkSurface, canPresent, instProc));
70     if (!ctx->isValid()) {
71         return nullptr;
72     }
73     return ctx;
74 }
75 
76 }  // namespace skwindow
77