xref: /aosp_15_r20/external/deqp/framework/platform/lnx/X11/tcuLnxX11Xcb.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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