Vulkan SDK for Android 1.1.1 Mali Developer Center
xcb.cpp
1 #define VK_USE_PLATFORM_XCB_KHR
2 #include "xcb.hpp"
3 #include <unistd.h>
4 #include <xcb/xcb_aux.h>
5 
6 using namespace std;
7 
8 namespace MaliSDK
9 {
10 Platform &Platform::get()
11 {
12  static XCBPlatform singleton;
13  return singleton;
14 }
15 
16 VkSurfaceKHR XCBPlatform::createSurface()
17 {
18  VkSurfaceKHR surface;
19  PFN_vkCreateXcbSurfaceKHR fpCreateXcbSurfaceKHR;
20  if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateXcbSurfaceKHR", fpCreateXcbSurfaceKHR))
21  return VK_NULL_HANDLE;
22 
23  VkXcbSurfaceCreateInfoKHR info = { VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR };
24  info.connection = connection;
25  info.window = window;
26 
27  VK_CHECK(fpCreateXcbSurfaceKHR(instance, &info, nullptr, &surface));
28  return surface;
29 }
30 
31 XCBPlatform::XCBPlatform()
32 {
33 }
34 
35 Platform::Status XCBPlatform::getWindowStatus()
36 {
37  return status;
38 }
39 
40 void XCBPlatform::handleEvents()
41 {
42  xcb_generic_event_t *event;
43  while ((event = xcb_poll_for_event(connection)) != nullptr)
44  {
45  auto code = event->response_type & ~0x80;
46  switch (code)
47  {
48  case XCB_CLIENT_MESSAGE:
49  if (reinterpret_cast<xcb_client_message_event_t *>(event)->data.data32[0] == atom_delete_window->atom)
50  status = STATUS_TEARDOWN;
51  break;
52 
53  case XCB_DESTROY_NOTIFY:
54  status = STATUS_TEARDOWN;
55  break;
56  }
57  free(event);
58  }
59 }
60 
61 Result XCBPlatform::initialize()
62 {
63  connection = xcb_connect(nullptr, nullptr);
64  if (xcb_connection_has_error(connection))
65  return RESULT_ERROR_IO;
66 
67  xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data;
68  window = xcb_generate_id(connection);
69  const uint32_t events[] = { XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT |
70  XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_ENTER_WINDOW |
71  XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE |
72  XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE |
73  XCB_EVENT_MASK_FOCUS_CHANGE };
74 
75  xcb_create_window(connection, XCB_COPY_FROM_PARENT, window, screen->root, 0, 0, 1280, 720, 0,
76  XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, XCB_CW_EVENT_MASK, events);
77 
78  xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, 8, "Mali SDK");
79 
80  xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window, XCB_ATOM_WM_ICON_NAME, XCB_ATOM_STRING, 8, 8,
81  "Mali SDK");
82 
83  auto cookie = xcb_intern_atom(connection, 1, 12, "WM_PROTOCOLS");
84  auto *reply = xcb_intern_atom_reply(connection, cookie, 0);
85 
86  cookie = xcb_intern_atom(connection, 0, 16, "WM_DELETE_WINDOW");
87  atom_delete_window = xcb_intern_atom_reply(connection, cookie, 0);
88  xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window, reply->atom, 4, 32, 1, &atom_delete_window->atom);
89 
90  free(reply);
91 
92  xcb_map_window(connection, window);
93  xcb_aux_sync(connection);
94  handleEvents();
95 
96  status = STATUS_RUNNING;
97 
98  return WSIPlatform::initialize();
99 }
100 
101 Platform::SwapchainDimensions XCBPlatform::getPreferredSwapchain()
102 {
103  SwapchainDimensions chain = { 1280, 720, VK_FORMAT_B8G8R8A8_UNORM };
104  return chain;
105 }
106 
107 Result XCBPlatform::createWindow(const SwapchainDimensions &swapchain)
108 {
109  return initVulkan(swapchain, { "VK_KHR_surface", "VK_KHR_xcb_surface" }, { "VK_KHR_swapchain" });
110 }
111 
112 void XCBPlatform::terminate()
113 {
114  if (connection)
115  {
116  xcb_aux_sync(connection);
117  handleEvents();
118 
119  WSIPlatform::terminate();
120 
121  xcb_destroy_window(connection, window);
122  xcb_disconnect(connection);
123  free(atom_delete_window);
124  connection = nullptr;
125  }
126 }
127 
128 XCBPlatform::~XCBPlatform()
129 {
130  terminate();
131 }
132 
133 Result XCBPlatform::presentImage(unsigned index)
134 {
135  handleEvents();
136 
137  if (status == STATUS_RUNNING)
138  {
139  Result res = WSIPlatform::presentImage(index);
140  xcb_flush(connection);
141  return res;
142  }
143  else
144  return RESULT_SUCCESS;
145 }
146 }
Describes the size and format of the swapchain.
Definition: platform.hpp:54
Status
Describes the status of the application lifecycle.
Definition: platform.hpp:65