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