1/*
2 * Copyright 2019 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
8#include "tools/sk_app/DawnWindowContext.h"
9#include "tools/sk_app/unix/WindowContextFactory_unix.h"
10#include "dawn_native/DawnNative.h"
11#include "dawn_native/VulkanBackend.h"
12#include "src/ports/SkOSLibrary.h"
13#include "tools/gpu/vk/VkTestUtils.h"
14
15#include <vulkan/vulkan.h>
16#include <X11/Xlib-xcb.h>
17
18using sk_app::window_context_factory::XlibWindowInfo;
19using sk_app::DisplayParams;
20using sk_app::DawnWindowContext;
21
22namespace sk_app {
23
24class DawnVulkanWindowContext_xlib : public DawnWindowContext {
25public:
26    DawnVulkanWindowContext_xlib(const XlibWindowInfo&, const DisplayParams&);
27    ~DawnVulkanWindowContext_xlib() override {}
28    wgpu::Device onInitializeContext() override;
29    void onDestroyContext() override {}
30    DawnSwapChainImplementation createSwapChainImplementation(
31            int width, int height, const DisplayParams& params) override;
32    void onSwapBuffers() override {}
33
34private:
35    Display*     fDisplay;
36    XWindow      fWindow;
37    VkSurfaceKHR fVkSurface = nullptr;
38
39    using INHERITED = DawnWindowContext;
40};
41
42DawnVulkanWindowContext_xlib::DawnVulkanWindowContext_xlib(const XlibWindowInfo& winInfo,
43                                                           const DisplayParams& params)
44        : INHERITED(params, wgpu::TextureFormat::BGRA8Unorm)
45        , fDisplay(winInfo.fDisplay)
46        , fWindow(winInfo.fWindow) {
47    XWindow root;
48    int x, y;
49    unsigned int border_width, depth;
50    unsigned int width, height;
51    XGetGeometry(fDisplay, fWindow, &root, &x, &y, &width, &height, &border_width, &depth);
52    this->initializeContext(width, height);
53}
54
55DawnSwapChainImplementation DawnVulkanWindowContext_xlib::createSwapChainImplementation(
56        int width, int height, const DisplayParams& params) {
57    return dawn_native::vulkan::CreateNativeSwapChainImpl(fDevice.Get(), fVkSurface);
58}
59
60wgpu::Device DawnVulkanWindowContext_xlib::onInitializeContext() {
61    wgpu::Device device = this->createDevice(dawn_native::BackendType::Vulkan);
62    if (!device) {
63        return nullptr;
64    }
65
66    void *vkLib = SkLoadDynamicLibrary("libvulkan.so.1");
67    if (!vkLib) {
68        return nullptr;
69    }
70    VkInstance instance = dawn_native::vulkan::GetInstance(device.Get());
71    if (!instance) {
72        return nullptr;
73    }
74    auto createXcbSurfaceKHR =
75        reinterpret_cast<PFN_vkCreateXcbSurfaceKHR>(SkGetProcedureAddress(vkLib,
76                                                                        "vkCreateXcbSurfaceKHR"));
77    if (!createXcbSurfaceKHR) {
78        printf("couldn't get extensions :(\n");
79        return nullptr;
80    }
81
82    VkXcbSurfaceCreateInfoKHR surfaceCreateInfo;
83    memset(&surfaceCreateInfo, 0, sizeof(VkXcbSurfaceCreateInfoKHR));
84    surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
85    surfaceCreateInfo.pNext = nullptr;
86    surfaceCreateInfo.flags = 0;
87    surfaceCreateInfo.connection = XGetXCBConnection(fDisplay);
88    surfaceCreateInfo.window = fWindow;
89
90    createXcbSurfaceKHR(instance, &surfaceCreateInfo, nullptr, &fVkSurface);
91    return device;
92}
93
94namespace window_context_factory {
95
96std::unique_ptr<WindowContext> MakeDawnVulkanForXlib(const XlibWindowInfo& winInfo,
97                                                     const DisplayParams& params) {
98    std::unique_ptr<WindowContext> ctx(new DawnVulkanWindowContext_xlib(winInfo, params));
99    if (!ctx->isValid()) {
100        return nullptr;
101    }
102    return ctx;
103}
104
105}
106
107}  // namespace sk_app
108