• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <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/linux/xcb/WindowSurfaceVkXcb.h"
18 #include "libANGLE/renderer/vulkan/vk_caps_utils.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     : DisplayVkLinux(state), mXcbConnection(nullptr), mHasXDisplay(false)
47 {}
48 
initialize(egl::Display * display)49 egl::Error DisplayVkXcb::initialize(egl::Display *display)
50 {
51     mHasXDisplay = !angle::GetEnvironmentVar("DISPLAY").empty();
52     if (mHasXDisplay)
53     {
54         mXcbConnection = xcb_connect(nullptr, nullptr);
55         ASSERT(mXcbConnection != nullptr);
56         int xcb_connection_error = xcb_connection_has_error(mXcbConnection);
57         if (xcb_connection_error)
58         {
59             ERR() << "xcb_connect() failed, error " << xcb_connection_error;
60             xcb_disconnect(mXcbConnection);
61             mXcbConnection = nullptr;
62             return egl::EglNotInitialized();
63         }
64     }
65     return DisplayVk::initialize(display);
66 }
67 
terminate()68 void DisplayVkXcb::terminate()
69 {
70     if (mHasXDisplay)
71     {
72         ASSERT(mXcbConnection != nullptr);
73         xcb_disconnect(mXcbConnection);
74         mXcbConnection = nullptr;
75     }
76     DisplayVk::terminate();
77 }
78 
isValidNativeWindow(EGLNativeWindowType window) const79 bool DisplayVkXcb::isValidNativeWindow(EGLNativeWindowType window) const
80 {
81     ASSERT(mHasXDisplay);
82     // There doesn't appear to be an xcb function explicitly for checking the validity of a
83     // window ID, but xcb_query_tree_reply will return nullptr if the window doesn't exist.
84     xcb_query_tree_cookie_t cookie =
85         xcb_query_tree(mXcbConnection, static_cast<xcb_window_t>(window));
86     xcb_query_tree_reply_t *reply = xcb_query_tree_reply(mXcbConnection, cookie, nullptr);
87     if (reply)
88     {
89         free(reply);
90         return true;
91     }
92     return false;
93 }
94 
createWindowSurfaceVk(const egl::SurfaceState & state,EGLNativeWindowType window)95 SurfaceImpl *DisplayVkXcb::createWindowSurfaceVk(const egl::SurfaceState &state,
96                                                  EGLNativeWindowType window)
97 {
98     ASSERT(mHasXDisplay);
99     return new WindowSurfaceVkXcb(state, window, mXcbConnection);
100 }
101 
generateConfigs()102 egl::ConfigSet DisplayVkXcb::generateConfigs()
103 {
104     const std::array<GLenum, 1> kColorFormats = {GL_BGRA8_EXT};
105 
106     std::vector<GLenum> depthStencilFormats(
107         egl_vk::kConfigDepthStencilFormats,
108         egl_vk::kConfigDepthStencilFormats + ArraySize(egl_vk::kConfigDepthStencilFormats));
109 
110     if (getCaps().stencil8)
111     {
112         depthStencilFormats.push_back(GL_STENCIL_INDEX8);
113     }
114     return egl_vk::GenerateConfigs(kColorFormats.data(), kColorFormats.size(),
115                                    depthStencilFormats.data(), depthStencilFormats.size(), this);
116 }
117 
checkConfigSupport(egl::Config * config)118 void DisplayVkXcb::checkConfigSupport(egl::Config *config)
119 {
120     // If no window system, cannot support windows.
121     if (!mHasXDisplay)
122     {
123         // No window support if no X11.
124         config->surfaceType &= ~EGL_WINDOW_BIT;
125         return;
126     }
127 
128     // TODO(geofflang): Test for native support and modify the config accordingly.
129     // http://anglebug.com/2692
130 
131     // Find the screen the window was created on:
132     xcb_screen_iterator_t screenIterator = xcb_setup_roots_iterator(xcb_get_setup(mXcbConnection));
133     ASSERT(screenIterator.rem);
134 
135     xcb_screen_t *screen = screenIterator.data;
136     ASSERT(screen);
137 
138     // Visual id is root_visual of the screen
139     config->nativeVisualID   = screen->root_visual;
140     config->nativeVisualType = GetXcbVisualType(screen);
141 }
142 
getWSIExtension() const143 const char *DisplayVkXcb::getWSIExtension() const
144 {
145     return VK_KHR_XCB_SURFACE_EXTENSION_NAME;
146 }
147 
IsVulkanXcbDisplayAvailable()148 bool IsVulkanXcbDisplayAvailable()
149 {
150     return true;
151 }
152 
CreateVulkanXcbDisplay(const egl::DisplayState & state)153 DisplayImpl *CreateVulkanXcbDisplay(const egl::DisplayState &state)
154 {
155     return new DisplayVkXcb(state);
156 }
157 
waitNativeImpl()158 angle::Result DisplayVkXcb::waitNativeImpl()
159 {
160     XSync(reinterpret_cast<Display *>(mState.displayId), False);
161     return angle::Result::Continue;
162 }
163 }  // namespace rx
164