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 
30 namespace vk
31 {
32 namespace wsi
33 {
34 
35 //! Get canonical WSI name that should be used for example in test case and group names.
getName(Type wsiType)36 const 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 
getExtensionName(Type wsiType)50 const 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 
getPlatformProperties(Type wsiType)64 const 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 
createSurface(const InstanceInterface & vki,VkInstance instance,Type wsiType,const Display & nativeDisplay,const Window & nativeWindow,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)123 VkResult 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 
createSurface(const InstanceInterface & vki,VkInstance instance,Type wsiType,const Display & nativeDisplay,const Window & nativeWindow,const VkAllocationCallbacks * pAllocator)236 Move<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 
getPhysicalDeviceSurfaceSupport(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,deUint32 queueFamilyIndex,VkSurfaceKHR surface)248 VkBool32 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 
getPhysicalDeviceSurfaceCapabilities(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface)260 VkSurfaceCapabilitiesKHR 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 
getPhysicalDeviceSurfaceFormats(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface)273 std::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 
getPhysicalDeviceSurfacePresentModes(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface)293 std::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 
getSwapchainImages(const DeviceInterface & vkd,VkDevice device,VkSwapchainKHR swapchain)313 std::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