1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
3 * ----------------------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief X11 using XCB utilities.
22 *//*--------------------------------------------------------------------*/
23
24 #include "tcuLnxX11Xcb.hpp"
25 #include "deMemory.h"
26
27 namespace tcu
28 {
29 namespace lnx
30 {
31 namespace x11
32 {
33
34 XcbDisplay::DisplayState XcbDisplay::s_displayState = XcbDisplay::DISPLAY_STATE_UNKNOWN;
35
hasDisplay(const char * name)36 bool XcbDisplay::hasDisplay(const char *name)
37 {
38 if (s_displayState == DISPLAY_STATE_UNKNOWN)
39 {
40 xcb_connection_t *connection = xcb_connect(name, NULL);
41 if (connection && !xcb_connection_has_error(connection))
42 {
43 s_displayState = DISPLAY_STATE_AVAILABLE;
44 xcb_disconnect(connection);
45 }
46 else
47 {
48 s_displayState = DISPLAY_STATE_UNAVAILABLE;
49 }
50 }
51 return s_displayState == DISPLAY_STATE_AVAILABLE ? true : false;
52 }
53
XcbDisplay(EventState & platform,const char * name)54 XcbDisplay::XcbDisplay(EventState &platform, const char *name) : DisplayBase(platform)
55 {
56 m_connection = xcb_connect(name, NULL);
57 const xcb_setup_t *setup = xcb_get_setup(m_connection);
58 xcb_screen_iterator_t iterator = xcb_setup_roots_iterator(setup);
59 m_screen = iterator.data;
60 }
61
~XcbDisplay(void)62 XcbDisplay::~XcbDisplay(void)
63 {
64 xcb_disconnect(m_connection);
65 }
66
processEvents(void)67 void XcbDisplay::processEvents(void)
68 {
69 xcb_generic_event_t *ev;
70 while ((ev = xcb_poll_for_event(m_connection)))
71 {
72 deFree(ev);
73 /* Manage your event */
74 }
75 }
76
XcbWindow(XcbDisplay & display,int width,int height,xcb_visualid_t * visual)77 XcbWindow::XcbWindow(XcbDisplay &display, int width, int height, xcb_visualid_t *visual)
78 : WindowBase()
79 , m_display(display)
80 {
81 xcb_connection_t *connection = m_display.getConnection();
82 uint32_t values[2];
83 m_window = xcb_generate_id(connection);
84 m_colormap = xcb_generate_id(connection);
85
86 if (visual == DE_NULL)
87 visual = &m_display.getScreen()->root_visual;
88
89 values[0] = m_display.getScreen()->white_pixel;
90 values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_PROPERTY_CHANGE;
91
92 xcb_create_window(connection, // Connection
93 XCB_COPY_FROM_PARENT, // depth (same as root)
94 m_window, // window Id
95 display.getScreen()->root, // parent window
96 0, 0, // x, y
97 static_cast<uint16_t>(width), // width
98 static_cast<uint16_t>(height), // height
99 10, // border_width
100 XCB_WINDOW_CLASS_INPUT_OUTPUT, // class
101 *visual, // visual
102 XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, // masks
103 values //not used yet
104 );
105
106 xcb_create_colormap(connection, XCB_COLORMAP_ALLOC_NONE, m_colormap, m_window, *visual);
107
108 xcb_alloc_color_reply_t *rep =
109 xcb_alloc_color_reply(connection, xcb_alloc_color(connection, m_colormap, 65535, 0, 0), NULL);
110 deFree(rep);
111 xcb_flush(connection);
112 }
113
~XcbWindow(void)114 XcbWindow::~XcbWindow(void)
115 {
116 xcb_flush(m_display.getConnection());
117 xcb_free_colormap(m_display.getConnection(), m_colormap);
118 xcb_destroy_window(m_display.getConnection(), m_window);
119 }
120
setVisibility(bool visible)121 void XcbWindow::setVisibility(bool visible)
122 {
123 if (visible == m_visible)
124 return;
125
126 if (visible)
127 xcb_map_window(m_display.getConnection(), m_window);
128 else
129 xcb_unmap_window(m_display.getConnection(), m_window);
130
131 m_visible = visible;
132 xcb_flush(m_display.getConnection());
133 }
134
processEvents(void)135 void XcbWindow::processEvents(void)
136 {
137 // A bit of a hack, since we don't really handle all the events.
138 m_display.processEvents();
139 }
140
getDimensions(int * width,int * height) const141 void XcbWindow::getDimensions(int *width, int *height) const
142 {
143 xcb_get_geometry_reply_t *geom;
144 geom =
145 xcb_get_geometry_reply(m_display.getConnection(), xcb_get_geometry(m_display.getConnection(), m_window), NULL);
146 *height = static_cast<int>(geom->height);
147 *width = static_cast<int>(geom->width);
148 deFree(geom);
149 }
150
setDimensions(int width,int height)151 void XcbWindow::setDimensions(int width, int height)
152 {
153 const uint32_t values[] = {static_cast<uint32_t>(width), static_cast<uint32_t>(height)};
154 xcb_void_cookie_t result;
155 xcb_connection_t *display = m_display.getConnection();
156 result = xcb_configure_window(display, m_window, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);
157 DE_ASSERT(DE_NULL == xcb_request_check(display, result));
158 xcb_flush(display);
159
160 for (;;)
161 {
162 xcb_generic_event_t *event = xcb_poll_for_event(display);
163 int w, h;
164 if (event != DE_NULL)
165 {
166 if (XCB_PROPERTY_NOTIFY == (event->response_type & ~0x80))
167 {
168 const xcb_property_notify_event_t *pnEvent = (xcb_property_notify_event_t *)event;
169 if (pnEvent->atom == XCB_ATOM_RESOLUTION)
170 {
171 deFree(event);
172 break;
173 }
174 }
175 deFree(event);
176 }
177 getDimensions(&w, &h);
178 if (h == height || w == width)
179 break;
180 }
181 }
182
183 } // namespace x11
184 } // namespace lnx
185 } // namespace tcu
186