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)
55 : DisplayBase (platform)
56 {
57 m_connection = xcb_connect(name, NULL);
58 const xcb_setup_t *setup = xcb_get_setup(m_connection);
59 xcb_screen_iterator_t iterator = xcb_setup_roots_iterator(setup);
60 m_screen = iterator.data;
61 }
62
~XcbDisplay(void)63 XcbDisplay::~XcbDisplay (void)
64 {
65 xcb_disconnect (m_connection);
66 }
67
processEvents(void)68 void XcbDisplay::processEvents (void)
69 {
70 xcb_generic_event_t *ev;
71 while ((ev = xcb_poll_for_event(m_connection)))
72 {
73 deFree(ev);
74 /* Manage your event */
75 }
76 }
77
XcbWindow(XcbDisplay & display,int width,int height,xcb_visualid_t * visual)78 XcbWindow::XcbWindow (XcbDisplay& display, int width, int height, xcb_visualid_t* visual)
79 : WindowBase ()
80 , m_display (display)
81 {
82 xcb_connection_t* connection = m_display.getConnection();
83 uint32_t values[2];
84 m_window = xcb_generate_id(connection);
85 m_colormap = xcb_generate_id(connection);
86
87 if (visual == DE_NULL)
88 visual = &m_display.getScreen()->root_visual;
89
90 values[0] = m_display.getScreen()->white_pixel;
91 values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_PROPERTY_CHANGE;
92
93 xcb_create_window (
94 connection, // Connection
95 XCB_COPY_FROM_PARENT, // depth (same as root)
96 m_window, // window Id
97 display.getScreen()->root, // parent window
98 0, 0, // x, y
99 static_cast<uint16_t >(width), // width
100 static_cast<uint16_t >(height), // height
101 10, // border_width
102 XCB_WINDOW_CLASS_INPUT_OUTPUT, // class
103 *visual, // visual
104 XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, // masks
105 values //not used yet
106 );
107
108 xcb_create_colormap (
109 connection,
110 XCB_COLORMAP_ALLOC_NONE,
111 m_colormap,
112 m_window,
113 *visual
114 );
115
116 xcb_alloc_color_reply_t* rep = xcb_alloc_color_reply(connection, xcb_alloc_color(connection, m_colormap, 65535, 0, 0), NULL);
117 deFree(rep);
118 xcb_flush (connection);
119 }
120
~XcbWindow(void)121 XcbWindow::~XcbWindow (void)
122 {
123 xcb_flush (m_display.getConnection());
124 xcb_free_colormap(m_display.getConnection(), m_colormap);
125 xcb_destroy_window(m_display.getConnection(), m_window);
126 }
127
setVisibility(bool visible)128 void XcbWindow::setVisibility (bool visible)
129 {
130 if (visible == m_visible)
131 return;
132
133 if (visible)
134 xcb_map_window(m_display.getConnection(), m_window);
135 else
136 xcb_unmap_window(m_display.getConnection(), m_window);
137
138 m_visible = visible;
139 xcb_flush (m_display.getConnection());
140
141 }
142
processEvents(void)143 void XcbWindow::processEvents (void)
144 {
145 // A bit of a hack, since we don't really handle all the events.
146 m_display.processEvents();
147 }
148
getDimensions(int * width,int * height) const149 void XcbWindow::getDimensions (int* width, int* height) const
150 {
151 xcb_get_geometry_reply_t *geom;
152 geom = xcb_get_geometry_reply(m_display.getConnection(), xcb_get_geometry(m_display.getConnection(), m_window), NULL);
153 *height = static_cast<int>(geom->height);
154 *width = static_cast<int>(geom->width);
155 deFree(geom);
156 }
157
setDimensions(int width,int height)158 void XcbWindow::setDimensions (int width, int height)
159 {
160 const uint32_t values[] = {static_cast<uint32_t >(width), static_cast<uint32_t >(height)};
161 xcb_void_cookie_t result;
162 xcb_connection_t* display = m_display.getConnection();
163 result = xcb_configure_window(display, m_window, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);
164 DE_ASSERT(DE_NULL == xcb_request_check(display,result));
165 xcb_flush (display);
166
167 for(;;)
168 {
169 xcb_generic_event_t* event = xcb_poll_for_event(display);
170 int w, h;
171 if(event != DE_NULL)
172 {
173 if (XCB_PROPERTY_NOTIFY == (event->response_type & ~0x80))
174 {
175 const xcb_property_notify_event_t* pnEvent = (xcb_property_notify_event_t*)event;
176 if (pnEvent->atom == XCB_ATOM_RESOLUTION)
177 {
178 deFree(event);
179 break;
180 }
181 }
182 deFree(event);
183 }
184 getDimensions (&w,&h);
185 if (h==height || w==width)
186 break;
187 }
188 }
189
190 } // xcb
191 } // lnx
192 } // tcu
193