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 Linux Vulkan Platform.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "tcuLnxVulkanPlatform.hpp"
25 #include "tcuLnxPlatform.hpp"
26 #include "vkWsiPlatform.hpp"
27 #include "gluPlatform.hpp"
28 #include "tcuLnx.hpp"
29 #include "tcuFunctionLibrary.hpp"
30 #include "deUniquePtr.hpp"
31 #include "deMemory.h"
32 
33 #include <sys/utsname.h>
34 
35 using de::MovePtr;
36 using de::UniquePtr;
37 
38 #if defined (DEQP_SUPPORT_X11)
39 #	include "tcuLnxX11.hpp"
40 #	if defined (DEQP_SUPPORT_XCB)
41 #		include "tcuLnxX11Xcb.hpp"
42 #	endif // DEQP_SUPPORT_XCB
43 #	define X11_DISPLAY ""
44 #endif // DEQP_SUPPORT_X11
45 
46 #if defined (DEQP_SUPPORT_WAYLAND)
47 #	include "tcuLnxWayland.hpp"
48 #	define WAYLAND_DISPLAY DE_NULL
49 #endif // DEQP_SUPPORT_WAYLAND
50 
51 namespace tcu
52 {
53 namespace lnx
54 {
55 
56 #if defined (DEQP_SUPPORT_X11)
57 
58 class VulkanWindowXlib : public vk::wsi::XlibWindowInterface
59 {
60 public:
VulkanWindowXlib(MovePtr<x11::XlibWindow> window)61 	VulkanWindowXlib (MovePtr<x11::XlibWindow> window)
62 		: vk::wsi::XlibWindowInterface	(vk::pt::XlibWindow(window->getXID()))
63 		, m_window						(window)
64 	{
65 	}
66 
setVisible(bool visible)67 	void setVisible(bool visible)
68 	{
69 		m_window->setVisibility(visible);
70 	}
71 
resize(const UVec2 & newSize)72 	void resize (const UVec2& newSize)
73 	{
74 		m_window->setDimensions((int)newSize.x(), (int)newSize.y());
75 	}
76 
77 private:
78 	UniquePtr<x11::XlibWindow>	m_window;
79 };
80 
81 class VulkanDisplayXlib : public vk::wsi::XlibDisplayInterface
82 {
83 public:
VulkanDisplayXlib(MovePtr<x11::DisplayBase> display)84 	VulkanDisplayXlib (MovePtr<x11::DisplayBase> display)
85 		: vk::wsi::XlibDisplayInterface	(vk::pt::XlibDisplayPtr(((x11::XlibDisplay*)display.get())->getXDisplay()))
86 		, m_display	(display)
87 	{
88 	}
89 
createWindow(const Maybe<UVec2> & initialSize) const90 	vk::wsi::Window* createWindow (const Maybe<UVec2>& initialSize) const
91 	{
92 		x11::XlibDisplay*	instance	= (x11::XlibDisplay*)(m_display.get());
93 		const deUint32		height		= !initialSize ? (deUint32)DEFAULT_WINDOW_HEIGHT : initialSize->y();
94 		const deUint32		width		= !initialSize ? (deUint32)DEFAULT_WINDOW_WIDTH : initialSize->x();
95 		return new VulkanWindowXlib(MovePtr<x11::XlibWindow>(new x11::XlibWindow(*instance, (int)width, (int)height, instance->getVisual(0))));
96 	}
97 
98 private:
99 	MovePtr<x11::DisplayBase> m_display;
100 };
101 
102 #endif // DEQP_SUPPORT_X11
103 
104 #if defined (DEQP_SUPPORT_XCB)
105 
106 class VulkanWindowXcb : public vk::wsi::XcbWindowInterface
107 {
108 public:
VulkanWindowXcb(MovePtr<x11::XcbWindow> window)109 	VulkanWindowXcb (MovePtr<x11::XcbWindow> window)
110 		: vk::wsi::XcbWindowInterface	(vk::pt::XcbWindow(window->getXID()))
111 		, m_window						(window)
112 	{
113 	}
114 
setVisible(bool visible)115 	void setVisible(bool visible)
116 	{
117 		m_window->setVisibility(visible);
118 	}
119 
resize(const UVec2 & newSize)120 	void resize (const UVec2& newSize)
121 	{
122 		m_window->setDimensions((int)newSize.x(), (int)newSize.y());
123 	}
124 
125 private:
126 	UniquePtr<x11::XcbWindow>	m_window;
127 };
128 
129 class VulkanDisplayXcb : public vk::wsi::XcbDisplayInterface
130 {
131 public:
VulkanDisplayXcb(MovePtr<x11::DisplayBase> display)132 	VulkanDisplayXcb (MovePtr<x11::DisplayBase> display)
133 		: vk::wsi::XcbDisplayInterface	(vk::pt::XcbConnectionPtr(((x11::XcbDisplay*)display.get())->getConnection()))
134 		, m_display		(display)
135 	{
136 	}
137 
createWindow(const Maybe<UVec2> & initialSize) const138 	vk::wsi::Window* createWindow (const Maybe<UVec2>& initialSize) const
139 	{
140 		x11::XcbDisplay*	instance	= (x11::XcbDisplay*)(m_display.get());
141 		const deUint32		height		= !initialSize ? (deUint32)DEFAULT_WINDOW_HEIGHT : initialSize->y();
142 		const deUint32		width		= !initialSize ? (deUint32)DEFAULT_WINDOW_WIDTH : initialSize->x();
143 		return new VulkanWindowXcb(MovePtr<x11::XcbWindow>(new x11::XcbWindow(*instance, (int)width, (int)height, DE_NULL)));
144 	}
145 
146 private:
147 	MovePtr<x11::DisplayBase> m_display;
148 };
149 #endif // DEQP_SUPPORT_XCB
150 
151 #if defined (DEQP_SUPPORT_WAYLAND)
152 class VulkanWindowWayland : public vk::wsi::WaylandWindowInterface
153 {
154 public:
VulkanWindowWayland(MovePtr<wayland::Window> window)155 	VulkanWindowWayland (MovePtr<wayland::Window> window)
156 		: vk::wsi::WaylandWindowInterface	(vk::pt::WaylandSurfacePtr(window->getSurface()))
157 		, m_window							(window)
158 	{
159 	}
160 
setVisible(bool visible)161 	void setVisible(bool visible)
162 	{
163 		m_window->setVisibility(visible);
164 	}
165 
resize(const UVec2 & newSize)166 	void resize (const UVec2& newSize)
167 	{
168 		m_window->setDimensions((int)newSize.x(), (int)newSize.y());
169 	}
170 
171 private:
172 	UniquePtr<wayland::Window>	m_window;
173 };
174 
175 class VulkanDisplayWayland : public vk::wsi::WaylandDisplayInterface
176 {
177 public:
VulkanDisplayWayland(MovePtr<wayland::Display> display)178 	VulkanDisplayWayland (MovePtr<wayland::Display> display)
179 		: vk::wsi::WaylandDisplayInterface	(vk::pt::WaylandDisplayPtr(display->getDisplay()))
180 		, m_display		(display)
181 	{
182 	}
183 
createWindow(const Maybe<UVec2> & initialSize) const184 	vk::wsi::Window* createWindow (const Maybe<UVec2>& initialSize) const
185 	{
186 		const deUint32	height		= !initialSize ? (deUint32)DEFAULT_WINDOW_HEIGHT : initialSize->y();
187 		const deUint32	width		= !initialSize ? (deUint32)DEFAULT_WINDOW_WIDTH : initialSize->x();
188 		return new VulkanWindowWayland(MovePtr<wayland::Window>(new wayland::Window(*m_display, (int)width, (int)height)));
189 	}
190 
191 private:
192 	MovePtr<wayland::Display> m_display;
193 };
194 #endif // DEQP_SUPPORT_WAYLAND
195 
196 #if defined (DEQP_SUPPORT_HEADLESS)
197 
198 struct VulkanWindowHeadless : public vk::wsi::Window
199 {
200 public:
resizetcu::lnx::VulkanWindowHeadless201 	void resize (const UVec2&)
202 	{
203 	}
204 };
205 
206 class VulkanDisplayHeadless : public vk::wsi::Display
207 {
208 public:
VulkanDisplayHeadless()209 	VulkanDisplayHeadless ()
210 	{
211 	}
212 
createWindow(const Maybe<UVec2> &) const213 	vk::wsi::Window* createWindow (const Maybe<UVec2>&) const
214 	{
215 		return new VulkanWindowHeadless();
216 	}
217 };
218 
219 #endif // DEQP_SUPPORT_HEADLESS
220 
221 class VulkanLibrary : public vk::Library
222 {
223 public:
VulkanLibrary(void)224 	VulkanLibrary (void)
225 		: m_library	("libvulkan.so.1")
226 		, m_driver	(m_library)
227 	{
228 	}
229 
getPlatformInterface(void) const230 	const vk::PlatformInterface&	getPlatformInterface	(void) const
231 	{
232 		return m_driver;
233 	}
234 
getFunctionLibrary(void) const235 	const tcu::FunctionLibrary&		getFunctionLibrary		(void) const
236 	{
237 		return m_library;
238 	}
239 
240 private:
241 	const DynamicFunctionLibrary	m_library;
242 	const vk::PlatformDriver		m_driver;
243 };
244 
VulkanPlatform(EventState & eventState)245 VulkanPlatform::VulkanPlatform (EventState& eventState)
246 	: m_eventState(eventState)
247 {
248 }
249 
createWsiDisplay(vk::wsi::Type wsiType) const250 vk::wsi::Display* VulkanPlatform::createWsiDisplay (vk::wsi::Type wsiType) const
251 {
252 	if (!hasDisplay(wsiType))
253 	{
254 	    throw NotSupportedError("This display type is not available: ", NULL, __FILE__, __LINE__);
255 	}
256 
257 	switch(wsiType)
258 	{
259 #if defined (DEQP_SUPPORT_X11)
260 	case vk::wsi::TYPE_XLIB:
261 		return new VulkanDisplayXlib(MovePtr<x11::DisplayBase>(new x11::XlibDisplay(m_eventState,X11_DISPLAY)));
262 		break;
263 #endif // DEQP_SUPPORT_X11
264 #if defined (DEQP_SUPPORT_XCB)
265 	case vk::wsi::TYPE_XCB:
266 		return new VulkanDisplayXcb(MovePtr<x11::DisplayBase>(new x11::XcbDisplay(m_eventState,X11_DISPLAY)));
267 		break;
268 #endif // DEQP_SUPPORT_XCB
269 #if defined (DEQP_SUPPORT_WAYLAND)
270 	case vk::wsi::TYPE_WAYLAND:
271 		return new VulkanDisplayWayland(MovePtr<wayland::Display>(new wayland::Display(m_eventState, WAYLAND_DISPLAY)));
272 		break;
273 #endif // DEQP_SUPPORT_WAYLAND
274 #if defined (DEQP_SUPPORT_HEADLESS)
275 	case vk::wsi::TYPE_HEADLESS:
276 		return new VulkanDisplayHeadless();
277 		break;
278 #endif // DEQP_SUPPORT_HEADLESS
279 
280 	default:
281 		TCU_THROW(NotSupportedError, "WSI type not supported");
282 
283 	};
284 }
hasDisplay(vk::wsi::Type wsiType) const285 bool VulkanPlatform::hasDisplay (vk::wsi::Type wsiType) const
286 {
287 	switch(wsiType)
288 	{
289 #if defined (DEQP_SUPPORT_X11)
290 	case vk::wsi::TYPE_XLIB:
291 		return x11::XlibDisplay::hasDisplay(X11_DISPLAY);
292 #endif // DEQP_SUPPORT_X11
293 #if defined (DEQP_SUPPORT_XCB)
294 	case vk::wsi::TYPE_XCB:
295 		return x11::XcbDisplay::hasDisplay(X11_DISPLAY);
296 #endif // DEQP_SUPPORT_XCB
297 #if defined (DEQP_SUPPORT_WAYLAND)
298 	case vk::wsi::TYPE_WAYLAND:
299 		return wayland::Display::hasDisplay(WAYLAND_DISPLAY);
300 #endif // DEQP_SUPPORT_WAYLAND
301 #if defined (DEQP_SUPPORT_HEADLESS)
302        case vk::wsi::TYPE_HEADLESS:
303                return true;
304 #endif // DEQP_SUPPORT_HEADLESS
305 	default:
306 		return false;
307 
308 	};
309 }
createLibrary(void) const310 vk::Library* VulkanPlatform::createLibrary (void) const
311 {
312 	return new VulkanLibrary();
313 }
314 
describePlatform(std::ostream & dst) const315 void VulkanPlatform::describePlatform (std::ostream& dst) const
316 {
317 	utsname		sysInfo;
318 	deMemset(&sysInfo, 0, sizeof(sysInfo));
319 
320 	if (uname(&sysInfo) != 0)
321 		throw std::runtime_error("uname() failed");
322 
323 	dst << "OS: " << sysInfo.sysname << " " << sysInfo.release << " " << sysInfo.version << "\n";
324 	dst << "CPU: " << sysInfo.machine << "\n";
325 }
326 
getMemoryLimits(vk::PlatformMemoryLimits & limits) const327 void VulkanPlatform::getMemoryLimits (vk::PlatformMemoryLimits& limits) const
328 {
329 	limits.totalSystemMemory					= 256*1024*1024;
330 	limits.totalDeviceLocalMemory				= 128*1024*1024;
331 	limits.deviceMemoryAllocationGranularity	= 64*1024;
332 	limits.devicePageSize						= 4096;
333 	limits.devicePageTableEntrySize				= 8;
334 	limits.devicePageTableHierarchyLevels		= 3;
335 }
336 
337 } // linux
338 } // tcu
339 
340