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/xcb/DisplayVkXcb.h"
11
12 #include <X11/Xutil.h>
13 #include <xcb/xcb.h>
14
15 #include "common/system_utils.h"
16 #include "libANGLE/Display.h"
17 #include "libANGLE/renderer/vulkan/vk_caps_utils.h"
18 #include "libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.h"
19
20 namespace rx
21 {
22
23 namespace
24 {
GetXcbVisualType(xcb_screen_t * screen)25 EGLint GetXcbVisualType(xcb_screen_t *screen)
26 {
27 // Visual type is the class member of xcb_visualtype_t whose id matches the root visual.
28 for (xcb_depth_iterator_t depth_iter = xcb_screen_allowed_depths_iterator(screen);
29 depth_iter.rem; xcb_depth_next(&depth_iter))
30 {
31 for (xcb_visualtype_iterator_t visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
32 visual_iter.rem; xcb_visualtype_next(&visual_iter))
33 {
34 if (screen->root_visual == visual_iter.data->visual_id)
35 {
36 return visual_iter.data->_class;
37 }
38 }
39 }
40
41 return EGL_NONE;
42 }
43 } // namespace
44
DisplayVkXcb(const egl::DisplayState & state)45 DisplayVkXcb::DisplayVkXcb(const egl::DisplayState &state)
46 : DisplayVk(state), mXcbConnection(nullptr)
47 {}
48
initialize(egl::Display * display)49 egl::Error DisplayVkXcb::initialize(egl::Display *display)
50 {
51 mXcbConnection = xcb_connect(nullptr, nullptr);
52 if (mXcbConnection == nullptr)
53 {
54 return egl::EglNotInitialized();
55 }
56 return DisplayVk::initialize(display);
57 }
58
terminate()59 void DisplayVkXcb::terminate()
60 {
61 ASSERT(mXcbConnection != nullptr);
62 xcb_disconnect(mXcbConnection);
63 mXcbConnection = nullptr;
64 DisplayVk::terminate();
65 }
66
isValidNativeWindow(EGLNativeWindowType window) const67 bool DisplayVkXcb::isValidNativeWindow(EGLNativeWindowType window) const
68 {
69 // There doesn't appear to be an xcb function explicitly for checking the validity of a
70 // window ID, but xcb_query_tree_reply will return nullptr if the window doesn't exist.
71 xcb_query_tree_cookie_t cookie =
72 xcb_query_tree(mXcbConnection, static_cast<xcb_window_t>(window));
73 xcb_query_tree_reply_t *reply = xcb_query_tree_reply(mXcbConnection, cookie, nullptr);
74 if (reply)
75 {
76 free(reply);
77 return true;
78 }
79 return false;
80 }
81
createWindowSurfaceVk(const egl::SurfaceState & state,EGLNativeWindowType window)82 SurfaceImpl *DisplayVkXcb::createWindowSurfaceVk(const egl::SurfaceState &state,
83 EGLNativeWindowType window)
84 {
85 return new WindowSurfaceVkXcb(state, window, mXcbConnection);
86 }
87
generateConfigs()88 egl::ConfigSet DisplayVkXcb::generateConfigs()
89 {
90 const std::array<GLenum, 1> kColorFormats = {GL_BGRA8_EXT};
91
92 std::vector<GLenum> depthStencilFormats(
93 egl_vk::kConfigDepthStencilFormats,
94 egl_vk::kConfigDepthStencilFormats + ArraySize(egl_vk::kConfigDepthStencilFormats));
95
96 if (getCaps().stencil8)
97 {
98 depthStencilFormats.push_back(GL_STENCIL_INDEX8);
99 }
100 return egl_vk::GenerateConfigs(kColorFormats.data(), kColorFormats.size(),
101 depthStencilFormats.data(), depthStencilFormats.size(), this);
102 }
103
checkConfigSupport(egl::Config * config)104 void DisplayVkXcb::checkConfigSupport(egl::Config *config)
105 {
106 // If no window system, cannot support windows.
107 static bool sNoX11Display = angle::GetEnvironmentVar("DISPLAY").empty();
108 if (sNoX11Display)
109 {
110 // No window support if no X11.
111 config->surfaceType &= ~EGL_WINDOW_BIT;
112 return;
113 }
114
115 // TODO(geofflang): Test for native support and modify the config accordingly.
116 // http://anglebug.com/2692
117
118 // Find the screen the window was created on:
119 xcb_screen_iterator_t screenIterator = xcb_setup_roots_iterator(xcb_get_setup(mXcbConnection));
120 ASSERT(screenIterator.rem);
121
122 xcb_screen_t *screen = screenIterator.data;
123 ASSERT(screen);
124
125 // Visual id is root_visual of the screen
126 config->nativeVisualID = screen->root_visual;
127 config->nativeVisualType = GetXcbVisualType(screen);
128 }
129
getWSIExtension() const130 const char *DisplayVkXcb::getWSIExtension() const
131 {
132 return VK_KHR_XCB_SURFACE_EXTENSION_NAME;
133 }
134
IsVulkanXcbDisplayAvailable()135 bool IsVulkanXcbDisplayAvailable()
136 {
137 return true;
138 }
139
CreateVulkanXcbDisplay(const egl::DisplayState & state)140 DisplayImpl *CreateVulkanXcbDisplay(const egl::DisplayState &state)
141 {
142 return new DisplayVkXcb(state);
143 }
144
waitNativeImpl()145 angle::Result DisplayVkXcb::waitNativeImpl()
146 {
147 XSync(reinterpret_cast<Display *>(mState.displayId), False);
148 return angle::Result::Continue;
149 }
150 } // namespace rx
151