1/*-------------------------------------------------------------------------
2 * Vulkan CTS Framework
3 * --------------------
4 *
5 * Copyright (c) 2016 Google 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 Windowing System Integration (WSI) Utilities.
22 *//*--------------------------------------------------------------------*/
23
24#include "vkWsiUtil.hpp"
25#include "deArrayUtil.hpp"
26#include "deMemory.h"
27
28#include <limits>
29
30namespace vk
31{
32namespace wsi
33{
34
35//! Get canonical WSI name that should be used for example in test case and group names.
36const char* getName (Type wsiType)
37{
38	static const char* const s_names[] =
39	{
40		"xlib",
41		"xcb",
42		"wayland",
43		"mir",
44		"android",
45		"win32",
46	};
47	return de::getSizedArrayElement<TYPE_LAST>(s_names, wsiType);
48}
49
50const char* getExtensionName (Type wsiType)
51{
52	static const char* const s_extNames[] =
53	{
54		"VK_KHR_xlib_surface",
55		"VK_KHR_xcb_surface",
56		"VK_KHR_wayland_surface",
57		"VK_KHR_mir_surface",
58		"VK_KHR_android_surface",
59		"VK_KHR_win32_surface",
60	};
61	return de::getSizedArrayElement<TYPE_LAST>(s_extNames, wsiType);
62}
63
64const PlatformProperties& getPlatformProperties (Type wsiType)
65{
66	// \note These are declared here (rather than queried through vk::Platform for example)
67	//		 on purpose. The behavior of a platform is partly defined by the platform spec,
68	//		 and partly by WSI extensions, and platform ports should not need to override
69	//		 that definition.
70
71	const deUint32	noDisplayLimit	= std::numeric_limits<deUint32>::max();
72	const deUint32	noWindowLimit	= std::numeric_limits<deUint32>::max();
73
74	static const PlatformProperties s_properties[] =
75	{
76		// VK_KHR_xlib_surface
77		{
78			PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE|PlatformProperties::FEATURE_RESIZE_WINDOW,
79			PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE,
80			noDisplayLimit,
81			noWindowLimit,
82		},
83		// VK_KHR_xcb_surface
84		{
85			PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE|PlatformProperties::FEATURE_RESIZE_WINDOW,
86			PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE,
87			noDisplayLimit,
88			noWindowLimit,
89		},
90		// VK_KHR_wayland_surface
91		{
92			0u,
93			PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE,
94			noDisplayLimit,
95			noWindowLimit,
96		},
97		// VK_KHR_mir_surface
98		{
99			PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE|PlatformProperties::FEATURE_RESIZE_WINDOW,
100			PlatformProperties::SWAPCHAIN_EXTENT_SCALED_TO_WINDOW_SIZE,
101			noDisplayLimit,
102			noWindowLimit,
103		},
104		// VK_KHR_android_surface
105		{
106			PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE,
107			PlatformProperties::SWAPCHAIN_EXTENT_SCALED_TO_WINDOW_SIZE,
108			1u,
109			1u, // Only one window available
110		},
111		// VK_KHR_win32_surface
112		{
113			PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE|PlatformProperties::FEATURE_RESIZE_WINDOW,
114			PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE,
115			noDisplayLimit,
116			noWindowLimit,
117		},
118	};
119
120	return de::getSizedArrayElement<TYPE_LAST>(s_properties, wsiType);
121}
122
123VkResult createSurface (const InstanceInterface&		vki,
124						VkInstance						instance,
125						Type							wsiType,
126						const Display&					nativeDisplay,
127						const Window&					nativeWindow,
128						const VkAllocationCallbacks*	pAllocator,
129						VkSurfaceKHR*					pSurface)
130{
131	// Update this function if you add more WSI implementations
132	DE_STATIC_ASSERT(TYPE_LAST == 6);
133
134	switch (wsiType)
135	{
136		case TYPE_XLIB:
137		{
138			const XlibDisplayInterface&			xlibDisplay		= dynamic_cast<const XlibDisplayInterface&>(nativeDisplay);
139			const XlibWindowInterface&			xlibWindow		= dynamic_cast<const XlibWindowInterface&>(nativeWindow);
140			const VkXlibSurfaceCreateInfoKHR	createInfo		=
141			{
142				VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
143				DE_NULL,
144				(VkXlibSurfaceCreateFlagsKHR)0,
145				xlibDisplay.getNative(),
146				xlibWindow.getNative()
147			};
148
149			return vki.createXlibSurfaceKHR(instance, &createInfo, pAllocator, pSurface);
150		}
151
152		case TYPE_XCB:
153		{
154			const XcbDisplayInterface&			xcbDisplay		= dynamic_cast<const XcbDisplayInterface&>(nativeDisplay);
155			const XcbWindowInterface&			xcbWindow		= dynamic_cast<const XcbWindowInterface&>(nativeWindow);
156			const VkXcbSurfaceCreateInfoKHR		createInfo		=
157			{
158				VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR,
159				DE_NULL,
160				(VkXcbSurfaceCreateFlagsKHR)0,
161				xcbDisplay.getNative(),
162				xcbWindow.getNative()
163			};
164
165			return vki.createXcbSurfaceKHR(instance, &createInfo, pAllocator, pSurface);
166		}
167
168		case TYPE_WAYLAND:
169		{
170			const WaylandDisplayInterface&		waylandDisplay	= dynamic_cast<const WaylandDisplayInterface&>(nativeDisplay);
171			const WaylandWindowInterface&		waylandWindow	= dynamic_cast<const WaylandWindowInterface&>(nativeWindow);
172			const VkWaylandSurfaceCreateInfoKHR	createInfo		=
173			{
174				VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR,
175				DE_NULL,
176				(VkWaylandSurfaceCreateFlagsKHR)0,
177				waylandDisplay.getNative(),
178				waylandWindow.getNative()
179			};
180
181			return vki.createWaylandSurfaceKHR(instance, &createInfo, pAllocator, pSurface);
182		}
183
184		case TYPE_MIR:
185		{
186			const MirDisplayInterface&			mirDisplay		= dynamic_cast<const MirDisplayInterface&>(nativeDisplay);
187			const MirWindowInterface&			mirWindow		= dynamic_cast<const MirWindowInterface&>(nativeWindow);
188			const VkMirSurfaceCreateInfoKHR		createInfo		=
189			{
190				VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR,
191				DE_NULL,
192				(VkXcbSurfaceCreateFlagsKHR)0,
193				mirDisplay.getNative(),
194				mirWindow.getNative()
195			};
196
197			return vki.createMirSurfaceKHR(instance, &createInfo, pAllocator, pSurface);
198		}
199
200		case TYPE_ANDROID:
201		{
202			const AndroidWindowInterface&		androidWindow	= dynamic_cast<const AndroidWindowInterface&>(nativeWindow);
203			const VkAndroidSurfaceCreateInfoKHR	createInfo		=
204			{
205				VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR,
206				DE_NULL,
207				(VkAndroidSurfaceCreateFlagsKHR)0,
208				androidWindow.getNative()
209			};
210
211			return vki.createAndroidSurfaceKHR(instance, &createInfo, pAllocator, pSurface);
212		}
213
214		case TYPE_WIN32:
215		{
216			const Win32DisplayInterface&		win32Display	= dynamic_cast<const Win32DisplayInterface&>(nativeDisplay);
217			const Win32WindowInterface&			win32Window		= dynamic_cast<const Win32WindowInterface&>(nativeWindow);
218			const VkWin32SurfaceCreateInfoKHR	createInfo		=
219			{
220				VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
221				DE_NULL,
222				(VkWin32SurfaceCreateFlagsKHR)0,
223				win32Display.getNative(),
224				win32Window.getNative()
225			};
226
227			return vki.createWin32SurfaceKHR(instance, &createInfo, pAllocator, pSurface);
228		}
229
230		default:
231			DE_FATAL("Unknown WSI type");
232			return VK_ERROR_SURFACE_LOST_KHR;
233	}
234}
235
236Move<VkSurfaceKHR> createSurface (const InstanceInterface&		vki,
237								  VkInstance					instance,
238								  Type							wsiType,
239								  const Display&				nativeDisplay,
240								  const Window&					nativeWindow,
241								  const VkAllocationCallbacks*	pAllocator)
242{
243	VkSurfaceKHR object = 0;
244	VK_CHECK(createSurface(vki, instance, wsiType, nativeDisplay, nativeWindow, pAllocator, &object));
245	return Move<VkSurfaceKHR>(check<VkSurfaceKHR>(object), Deleter<VkSurfaceKHR>(vki, instance, pAllocator));
246}
247
248VkBool32 getPhysicalDeviceSurfaceSupport (const InstanceInterface&	vki,
249										  VkPhysicalDevice			physicalDevice,
250										  deUint32					queueFamilyIndex,
251										  VkSurfaceKHR				surface)
252{
253	VkBool32 result = 0;
254
255	VK_CHECK(vki.getPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, &result));
256
257	return result;
258}
259
260VkSurfaceCapabilitiesKHR getPhysicalDeviceSurfaceCapabilities (const InstanceInterface&		vki,
261															   VkPhysicalDevice				physicalDevice,
262															   VkSurfaceKHR					surface)
263{
264	VkSurfaceCapabilitiesKHR capabilities;
265
266	deMemset(&capabilities, 0, sizeof(capabilities));
267
268	VK_CHECK(vki.getPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &capabilities));
269
270	return capabilities;
271}
272
273std::vector<VkSurfaceFormatKHR> getPhysicalDeviceSurfaceFormats (const InstanceInterface&		vki,
274																 VkPhysicalDevice				physicalDevice,
275																 VkSurfaceKHR					surface)
276{
277	deUint32	numFormats	= 0;
278
279	VK_CHECK(vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &numFormats, DE_NULL));
280
281	if (numFormats > 0)
282	{
283		std::vector<VkSurfaceFormatKHR>	formats	(numFormats);
284
285		VK_CHECK(vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &numFormats, &formats[0]));
286
287		return formats;
288	}
289	else
290		return std::vector<VkSurfaceFormatKHR>();
291}
292
293std::vector<VkPresentModeKHR> getPhysicalDeviceSurfacePresentModes (const InstanceInterface&		vki,
294																	VkPhysicalDevice				physicalDevice,
295																	VkSurfaceKHR					surface)
296{
297	deUint32	numModes	= 0;
298
299	VK_CHECK(vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &numModes, DE_NULL));
300
301	if (numModes > 0)
302	{
303		std::vector<VkPresentModeKHR>	modes	(numModes);
304
305		VK_CHECK(vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &numModes, &modes[0]));
306
307		return modes;
308	}
309	else
310		return std::vector<VkPresentModeKHR>();
311}
312
313std::vector<VkImage> getSwapchainImages (const DeviceInterface&			vkd,
314					 					 VkDevice						device,
315					 					 VkSwapchainKHR					swapchain)
316{
317	deUint32	numImages	= 0;
318
319	VK_CHECK(vkd.getSwapchainImagesKHR(device, swapchain, &numImages, DE_NULL));
320
321	if (numImages > 0)
322	{
323		std::vector<VkImage>	images	(numImages);
324
325		VK_CHECK(vkd.getSwapchainImagesKHR(device, swapchain, &numImages, &images[0]));
326
327		return images;
328	}
329	else
330		return std::vector<VkImage>();
331}
332
333} // wsi
334} // vk
335