xref: /aosp_15_r20/external/deqp/framework/platform/lnx/wayland/tcuLnxWayland.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Tester Core
3  * ----------------------------------------
4  *
5  * Copyright (c) 2014 The Android Open Source Project
6  * Copyright (c) 2016 The Khronos Group Inc.
7  * Copyright (c) 2016 Mun Gwan-gyeong <[email protected]>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief wayland utilities.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "tcuLnxWayland.hpp"
27 #include "gluRenderConfig.hpp"
28 #include "deMemory.h"
29 
30 #include <stdio.h>
31 
32 namespace tcu
33 {
34 namespace lnx
35 {
36 namespace wayland
37 {
38 
39 const struct wl_registry_listener Display::s_registryListener
40 {
41     Display::handleGlobal, Display::handleGlobalRemove
42 };
43 
44 Display::DisplayState Display::s_displayState = Display::DISPLAY_STATE_UNKNOWN;
45 
46 bool Window::s_addWMBaseListener = true;
47 
48 const struct xdg_surface_listener Window::s_xdgSurfaceListener
49 {
50     Window::handleConfigure
51 };
52 
53 const struct xdg_wm_base_listener Window::s_wmBaseListener
54 {
55     Window::handlePing
56 };
57 
handleGlobal(void * data,struct wl_registry * registry,uint32_t id,const char * interface,uint32_t version)58 void Display::handleGlobal(void *data, struct wl_registry *registry, uint32_t id, const char *interface,
59                            uint32_t version)
60 {
61     Display *_this = static_cast<Display *>(data);
62     DE_UNREF(version);
63 
64     if (!strcmp(interface, "wl_compositor"))
65         _this->m_compositor = static_cast<struct wl_compositor *>(
66             wl_registry_bind(registry, id, &wl_compositor_interface, version > 3 ? version : 3));
67     if (!strcmp(interface, "xdg_wm_base"))
68         _this->m_shell = static_cast<struct xdg_wm_base *>(wl_registry_bind(registry, id, &xdg_wm_base_interface, 1));
69 }
70 
handleGlobalRemove(void * data,struct wl_registry * registry,uint32_t name)71 void Display::handleGlobalRemove(void *data, struct wl_registry *registry, uint32_t name)
72 {
73     DE_UNREF(data);
74     DE_UNREF(registry);
75     DE_UNREF(name);
76 }
77 
hasDisplay(const char * name)78 bool Display::hasDisplay(const char *name)
79 {
80     if (s_displayState == DISPLAY_STATE_UNKNOWN)
81     {
82         struct wl_display *display = wl_display_connect(name);
83         if (display)
84         {
85             s_displayState = DISPLAY_STATE_AVAILABLE;
86             wl_display_disconnect(display);
87         }
88         else
89             s_displayState = DISPLAY_STATE_UNAVAILABLE;
90     }
91     return s_displayState == DISPLAY_STATE_AVAILABLE ? true : false;
92 }
93 
Display(EventState & eventState,const char * name)94 Display::Display(EventState &eventState, const char *name)
95     : m_eventState(eventState)
96     , m_display(DE_NULL)
97     , m_registry(DE_NULL)
98     , m_compositor(DE_NULL)
99     , m_shell(DE_NULL)
100 {
101     try
102     {
103         m_display = wl_display_connect(name);
104         if (!m_display)
105             throw ResourceError("Failed to open display", name, __FILE__, __LINE__);
106 
107         m_registry = wl_display_get_registry(m_display);
108         if (!m_registry)
109             throw ResourceError("Failed to get registry", name, __FILE__, __LINE__);
110 
111         wl_registry_add_listener(m_registry, &s_registryListener, this);
112         wl_display_roundtrip(m_display);
113         if (!m_compositor)
114             throw ResourceError("Failed to bind compositor", name, __FILE__, __LINE__);
115         if (!m_shell)
116             throw ResourceError("Failed to bind shell", name, __FILE__, __LINE__);
117     }
118     catch (...)
119     {
120         if (m_shell)
121             xdg_wm_base_destroy(m_shell);
122 
123         if (m_compositor)
124             wl_compositor_destroy(m_compositor);
125 
126         if (m_registry)
127             wl_registry_destroy(m_registry);
128 
129         if (m_display)
130             wl_display_disconnect(m_display);
131 
132         throw;
133     }
134 }
135 
~Display(void)136 Display::~Display(void)
137 {
138     if (m_shell)
139         xdg_wm_base_destroy(m_shell);
140 
141     if (m_compositor)
142         wl_compositor_destroy(m_compositor);
143 
144     if (m_registry)
145         wl_registry_destroy(m_registry);
146 
147     if (m_display)
148         wl_display_disconnect(m_display);
149 }
150 
processEvents(void)151 void Display::processEvents(void)
152 {
153 }
154 
Window(Display & display,int width,int height)155 Window::Window(Display &display, int width, int height) : m_display(display)
156 {
157     try
158     {
159         m_surface = wl_compositor_create_surface(display.getCompositor());
160         if (!m_surface)
161             throw ResourceError("Failed to create ", "surface", __FILE__, __LINE__);
162 
163         m_xdgSurface = xdg_wm_base_get_xdg_surface(display.getShell(), m_surface);
164         if (!m_xdgSurface)
165             throw ResourceError("Failed to create ", "shell_surface", __FILE__, __LINE__);
166 
167         // add wm base listener once
168         if (s_addWMBaseListener)
169         {
170             xdg_wm_base_add_listener(display.getShell(), &s_wmBaseListener, this);
171             s_addWMBaseListener = false;
172         }
173         xdg_surface_add_listener(m_xdgSurface, &s_xdgSurfaceListener, this);
174 
175         // select xdg surface role
176         m_topLevel = xdg_surface_get_toplevel(m_xdgSurface);
177         xdg_toplevel_set_title(m_topLevel, "CTS for OpenGL (ES)");
178 
179         // configure xdg surface
180         m_configured = false;
181         wl_surface_commit(m_surface);
182 
183         // wait till xdg surface is configured
184         int dispatchedEvents = 0;
185         while (dispatchedEvents != -1)
186         {
187             dispatchedEvents = wl_display_dispatch(display.getDisplay());
188             if (m_configured)
189                 break;
190         }
191 
192         if (width == glu::RenderConfig::DONT_CARE)
193             width = DEFAULT_WINDOW_WIDTH;
194         if (height == glu::RenderConfig::DONT_CARE)
195             height = DEFAULT_WINDOW_HEIGHT;
196 
197         m_window = wl_egl_window_create(m_surface, width, height);
198         if (!m_window)
199             throw ResourceError("Failed to create ", "window", __FILE__, __LINE__);
200     }
201     catch (...)
202     {
203         throw;
204     }
205     TCU_CHECK(m_window);
206 }
207 
setVisibility(bool visible)208 void Window::setVisibility(bool visible)
209 {
210     m_visible = visible;
211 }
212 
getDimensions(int * width,int * height) const213 void Window::getDimensions(int *width, int *height) const
214 {
215     wl_egl_window_get_attached_size(m_window, width, height);
216 }
217 
setDimensions(int width,int height)218 void Window::setDimensions(int width, int height)
219 {
220     wl_egl_window_resize(m_window, width, height, 0, 0);
221 }
222 
processEvents(void)223 void Window::processEvents(void)
224 {
225 }
226 
handlePing(void * data,struct xdg_wm_base * shell,uint32_t serial)227 void Window::handlePing(void *data, struct xdg_wm_base *shell, uint32_t serial)
228 {
229     DE_UNREF(data);
230     xdg_wm_base_pong(shell, serial);
231 }
232 
handleConfigure(void * data,struct xdg_surface * xdgSurface,uint32_t serial)233 void Window::handleConfigure(void *data, struct xdg_surface *xdgSurface, uint32_t serial)
234 {
235     Window *window       = reinterpret_cast<Window *>(data);
236     window->m_configured = true;
237 
238     xdg_surface_ack_configure(xdgSurface, serial);
239 }
240 
~Window(void)241 Window::~Window(void)
242 {
243     if (m_window)
244         wl_egl_window_destroy(m_window);
245     if (m_topLevel)
246         xdg_toplevel_destroy(m_topLevel);
247     if (m_xdgSurface)
248         xdg_surface_destroy(m_xdgSurface);
249     if (m_surface)
250         wl_surface_destroy(m_surface);
251 }
252 
253 } // namespace wayland
254 } // namespace lnx
255 } // namespace tcu
256