xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/linux/xcb/DisplayVkXcb.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // DisplayVkXcb.cpp:
7 //    Implements the class methods for DisplayVkXcb.
8 //
9 
10 #include "libANGLE/renderer/vulkan/linux/xcb/DisplayVkXcb.h"
11 
12 #include <xcb/xcb.h>
13 
14 #include "common/system_utils.h"
15 #include "libANGLE/Display.h"
16 #include "libANGLE/renderer/vulkan/linux/xcb/WindowSurfaceVkXcb.h"
17 #include "libANGLE/renderer/vulkan/vk_caps_utils.h"
18 
19 namespace rx
20 {
21 
22 namespace
23 {
GetXcbVisualType(xcb_screen_t * screen)24 EGLint GetXcbVisualType(xcb_screen_t *screen)
25 {
26     // Visual type is the class member of xcb_visualtype_t whose id matches the root visual.
27     for (xcb_depth_iterator_t depth_iter = xcb_screen_allowed_depths_iterator(screen);
28          depth_iter.rem; xcb_depth_next(&depth_iter))
29     {
30         for (xcb_visualtype_iterator_t visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
31              visual_iter.rem; xcb_visualtype_next(&visual_iter))
32         {
33             if (screen->root_visual == visual_iter.data->visual_id)
34             {
35                 return visual_iter.data->_class;
36             }
37         }
38     }
39 
40     return EGL_NONE;
41 }
42 }  // namespace
43 
DisplayVkXcb(const egl::DisplayState & state)44 DisplayVkXcb::DisplayVkXcb(const egl::DisplayState &state)
45     : DisplayVkLinux(state), mXcbConnection(nullptr), mHasXDisplay(false)
46 {}
47 
initialize(egl::Display * display)48 egl::Error DisplayVkXcb::initialize(egl::Display *display)
49 {
50     mHasXDisplay = !angle::GetEnvironmentVar("DISPLAY").empty();
51     if (mHasXDisplay)
52     {
53         mXcbConnection = xcb_connect(nullptr, nullptr);
54         ASSERT(mXcbConnection != nullptr);
55         int xcb_connection_error = xcb_connection_has_error(mXcbConnection);
56         if (xcb_connection_error)
57         {
58             ERR() << "xcb_connect() failed, error " << xcb_connection_error;
59             xcb_disconnect(mXcbConnection);
60             mXcbConnection = nullptr;
61             return egl::EglNotInitialized();
62         }
63     }
64     return DisplayVk::initialize(display);
65 }
66 
terminate()67 void DisplayVkXcb::terminate()
68 {
69     if (mHasXDisplay)
70     {
71         ASSERT(mXcbConnection != nullptr);
72         xcb_disconnect(mXcbConnection);
73         mXcbConnection = nullptr;
74     }
75     DisplayVk::terminate();
76 }
77 
isValidNativeWindow(EGLNativeWindowType window) const78 bool DisplayVkXcb::isValidNativeWindow(EGLNativeWindowType window) const
79 {
80     ASSERT(mHasXDisplay);
81     // There doesn't appear to be an xcb function explicitly for checking the validity of a
82     // window ID, but xcb_query_tree_reply will return nullptr if the window doesn't exist.
83     xcb_query_tree_cookie_t cookie =
84         xcb_query_tree(mXcbConnection, static_cast<xcb_window_t>(window));
85     xcb_query_tree_reply_t *reply = xcb_query_tree_reply(mXcbConnection, cookie, nullptr);
86     if (reply)
87     {
88         free(reply);
89         return true;
90     }
91     return false;
92 }
93 
createWindowSurfaceVk(const egl::SurfaceState & state,EGLNativeWindowType window)94 SurfaceImpl *DisplayVkXcb::createWindowSurfaceVk(const egl::SurfaceState &state,
95                                                  EGLNativeWindowType window)
96 {
97     ASSERT(mHasXDisplay);
98     return new WindowSurfaceVkXcb(state, window, mXcbConnection);
99 }
100 
generateConfigs()101 egl::ConfigSet DisplayVkXcb::generateConfigs()
102 {
103     const std::array<GLenum, 1> kColorFormats = {GL_BGRA8_EXT};
104 
105     std::vector<GLenum> depthStencilFormats(
106         egl_vk::kConfigDepthStencilFormats,
107         egl_vk::kConfigDepthStencilFormats + ArraySize(egl_vk::kConfigDepthStencilFormats));
108 
109     if (getCaps().stencil8)
110     {
111         depthStencilFormats.push_back(GL_STENCIL_INDEX8);
112     }
113     return egl_vk::GenerateConfigs(kColorFormats.data(), kColorFormats.size(),
114                                    depthStencilFormats.data(), depthStencilFormats.size(), this);
115 }
116 
checkConfigSupport(egl::Config * config)117 void DisplayVkXcb::checkConfigSupport(egl::Config *config)
118 {
119     // If no window system, cannot support windows.
120     if (!mHasXDisplay)
121     {
122         // No window support if no X11.
123         config->surfaceType &= ~EGL_WINDOW_BIT;
124         return;
125     }
126 
127     // TODO(geofflang): Test for native support and modify the config accordingly.
128     // http://anglebug.com/42261400
129 
130     // Find the screen the window was created on:
131     xcb_screen_iterator_t screenIterator = xcb_setup_roots_iterator(xcb_get_setup(mXcbConnection));
132     ASSERT(screenIterator.rem);
133 
134     xcb_screen_t *screen = screenIterator.data;
135     ASSERT(screen);
136 
137     // Visual id is root_visual of the screen
138     config->nativeVisualID   = screen->root_visual;
139     config->nativeVisualType = GetXcbVisualType(screen);
140 }
141 
getWSIExtension() const142 const char *DisplayVkXcb::getWSIExtension() const
143 {
144     return VK_KHR_XCB_SURFACE_EXTENSION_NAME;
145 }
146 
IsVulkanXcbDisplayAvailable()147 bool IsVulkanXcbDisplayAvailable()
148 {
149     return true;
150 }
151 
CreateVulkanXcbDisplay(const egl::DisplayState & state)152 DisplayImpl *CreateVulkanXcbDisplay(const egl::DisplayState &state)
153 {
154     return new DisplayVkXcb(state);
155 }
156 
waitNativeImpl()157 angle::Result DisplayVkXcb::waitNativeImpl()
158 {
159     // The following is the implementation of xcb_aux_sync (equivalent of XSync).  xcb_aux_sync is
160     // not called directly because it's in the libxcb-util package, which Chrome does not want to
161     // depend on (due to different package versions in popular distros).
162     free(xcb_get_input_focus_reply(mXcbConnection, xcb_get_input_focus(mXcbConnection), nullptr));
163     return angle::Result::Continue;
164 }
165 }  // namespace rx
166