1b877906bSopenharmony_ci//======================================================================== 2b877906bSopenharmony_ci// GLFW 3.5 - www.glfw.org 3b877906bSopenharmony_ci//------------------------------------------------------------------------ 4b877906bSopenharmony_ci// Copyright (c) 2002-2006 Marcus Geelnard 5b877906bSopenharmony_ci// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org> 6b877906bSopenharmony_ci// 7b877906bSopenharmony_ci// This software is provided 'as-is', without any express or implied 8b877906bSopenharmony_ci// warranty. In no event will the authors be held liable for any damages 9b877906bSopenharmony_ci// arising from the use of this software. 10b877906bSopenharmony_ci// 11b877906bSopenharmony_ci// Permission is granted to anyone to use this software for any purpose, 12b877906bSopenharmony_ci// including commercial applications, and to alter it and redistribute it 13b877906bSopenharmony_ci// freely, subject to the following restrictions: 14b877906bSopenharmony_ci// 15b877906bSopenharmony_ci// 1. The origin of this software must not be misrepresented; you must not 16b877906bSopenharmony_ci// claim that you wrote the original software. If you use this software 17b877906bSopenharmony_ci// in a product, an acknowledgment in the product documentation would 18b877906bSopenharmony_ci// be appreciated but is not required. 19b877906bSopenharmony_ci// 20b877906bSopenharmony_ci// 2. Altered source versions must be plainly marked as such, and must not 21b877906bSopenharmony_ci// be misrepresented as being the original software. 22b877906bSopenharmony_ci// 23b877906bSopenharmony_ci// 3. This notice may not be removed or altered from any source 24b877906bSopenharmony_ci// distribution. 25b877906bSopenharmony_ci// 26b877906bSopenharmony_ci//======================================================================== 27b877906bSopenharmony_ci 28b877906bSopenharmony_ci#include "internal.h" 29b877906bSopenharmony_ci 30b877906bSopenharmony_ci#include <assert.h> 31b877906bSopenharmony_ci#include <string.h> 32b877906bSopenharmony_ci#include <stdlib.h> 33b877906bSopenharmony_ci 34b877906bSopenharmony_ci#define _GLFW_FIND_LOADER 1 35b877906bSopenharmony_ci#define _GLFW_REQUIRE_LOADER 2 36b877906bSopenharmony_ci 37b877906bSopenharmony_ci 38b877906bSopenharmony_ci////////////////////////////////////////////////////////////////////////// 39b877906bSopenharmony_ci////// GLFW internal API ////// 40b877906bSopenharmony_ci////////////////////////////////////////////////////////////////////////// 41b877906bSopenharmony_ci 42b877906bSopenharmony_ciGLFWbool _glfwInitVulkan(int mode) 43b877906bSopenharmony_ci{ 44b877906bSopenharmony_ci VkResult err; 45b877906bSopenharmony_ci VkExtensionProperties* ep; 46b877906bSopenharmony_ci PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties; 47b877906bSopenharmony_ci uint32_t i, count; 48b877906bSopenharmony_ci 49b877906bSopenharmony_ci if (_glfw.vk.available) 50b877906bSopenharmony_ci return GLFW_TRUE; 51b877906bSopenharmony_ci 52b877906bSopenharmony_ci if (_glfw.hints.init.vulkanLoader) 53b877906bSopenharmony_ci _glfw.vk.GetInstanceProcAddr = _glfw.hints.init.vulkanLoader; 54b877906bSopenharmony_ci else 55b877906bSopenharmony_ci { 56b877906bSopenharmony_ci#if defined(_GLFW_VULKAN_LIBRARY) 57b877906bSopenharmony_ci _glfw.vk.handle = _glfwPlatformLoadModule(_GLFW_VULKAN_LIBRARY); 58b877906bSopenharmony_ci#elif defined(_GLFW_WIN32) 59b877906bSopenharmony_ci _glfw.vk.handle = _glfwPlatformLoadModule("vulkan-1.dll"); 60b877906bSopenharmony_ci#elif defined(_GLFW_COCOA) 61b877906bSopenharmony_ci _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib"); 62b877906bSopenharmony_ci if (!_glfw.vk.handle) 63b877906bSopenharmony_ci _glfw.vk.handle = _glfwLoadLocalVulkanLoaderCocoa(); 64b877906bSopenharmony_ci#elif defined(__OpenBSD__) || defined(__NetBSD__) 65b877906bSopenharmony_ci _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so"); 66b877906bSopenharmony_ci#else 67b877906bSopenharmony_ci _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so.1"); 68b877906bSopenharmony_ci#endif 69b877906bSopenharmony_ci if (!_glfw.vk.handle) 70b877906bSopenharmony_ci { 71b877906bSopenharmony_ci if (mode == _GLFW_REQUIRE_LOADER) 72b877906bSopenharmony_ci _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found"); 73b877906bSopenharmony_ci 74b877906bSopenharmony_ci return GLFW_FALSE; 75b877906bSopenharmony_ci } 76b877906bSopenharmony_ci 77b877906bSopenharmony_ci _glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) 78b877906bSopenharmony_ci _glfwPlatformGetModuleSymbol(_glfw.vk.handle, "vkGetInstanceProcAddr"); 79b877906bSopenharmony_ci if (!_glfw.vk.GetInstanceProcAddr) 80b877906bSopenharmony_ci { 81b877906bSopenharmony_ci _glfwInputError(GLFW_API_UNAVAILABLE, 82b877906bSopenharmony_ci "Vulkan: Loader does not export vkGetInstanceProcAddr"); 83b877906bSopenharmony_ci 84b877906bSopenharmony_ci _glfwTerminateVulkan(); 85b877906bSopenharmony_ci return GLFW_FALSE; 86b877906bSopenharmony_ci } 87b877906bSopenharmony_ci } 88b877906bSopenharmony_ci 89b877906bSopenharmony_ci vkEnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties) 90b877906bSopenharmony_ci vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties"); 91b877906bSopenharmony_ci if (!vkEnumerateInstanceExtensionProperties) 92b877906bSopenharmony_ci { 93b877906bSopenharmony_ci _glfwInputError(GLFW_API_UNAVAILABLE, 94b877906bSopenharmony_ci "Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties"); 95b877906bSopenharmony_ci 96b877906bSopenharmony_ci _glfwTerminateVulkan(); 97b877906bSopenharmony_ci return GLFW_FALSE; 98b877906bSopenharmony_ci } 99b877906bSopenharmony_ci 100b877906bSopenharmony_ci err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL); 101b877906bSopenharmony_ci if (err) 102b877906bSopenharmony_ci { 103b877906bSopenharmony_ci // NOTE: This happens on systems with a loader but without any Vulkan ICD 104b877906bSopenharmony_ci if (mode == _GLFW_REQUIRE_LOADER) 105b877906bSopenharmony_ci { 106b877906bSopenharmony_ci _glfwInputError(GLFW_API_UNAVAILABLE, 107b877906bSopenharmony_ci "Vulkan: Failed to query instance extension count: %s", 108b877906bSopenharmony_ci _glfwGetVulkanResultString(err)); 109b877906bSopenharmony_ci } 110b877906bSopenharmony_ci 111b877906bSopenharmony_ci _glfwTerminateVulkan(); 112b877906bSopenharmony_ci return GLFW_FALSE; 113b877906bSopenharmony_ci } 114b877906bSopenharmony_ci 115b877906bSopenharmony_ci ep = _glfw_calloc(count, sizeof(VkExtensionProperties)); 116b877906bSopenharmony_ci 117b877906bSopenharmony_ci err = vkEnumerateInstanceExtensionProperties(NULL, &count, ep); 118b877906bSopenharmony_ci if (err) 119b877906bSopenharmony_ci { 120b877906bSopenharmony_ci _glfwInputError(GLFW_API_UNAVAILABLE, 121b877906bSopenharmony_ci "Vulkan: Failed to query instance extensions: %s", 122b877906bSopenharmony_ci _glfwGetVulkanResultString(err)); 123b877906bSopenharmony_ci 124b877906bSopenharmony_ci _glfw_free(ep); 125b877906bSopenharmony_ci _glfwTerminateVulkan(); 126b877906bSopenharmony_ci return GLFW_FALSE; 127b877906bSopenharmony_ci } 128b877906bSopenharmony_ci 129b877906bSopenharmony_ci for (i = 0; i < count; i++) 130b877906bSopenharmony_ci { 131b877906bSopenharmony_ci if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0) 132b877906bSopenharmony_ci _glfw.vk.KHR_surface = GLFW_TRUE; 133b877906bSopenharmony_ci else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0) 134b877906bSopenharmony_ci _glfw.vk.KHR_win32_surface = GLFW_TRUE; 135b877906bSopenharmony_ci else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0) 136b877906bSopenharmony_ci _glfw.vk.MVK_macos_surface = GLFW_TRUE; 137b877906bSopenharmony_ci else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0) 138b877906bSopenharmony_ci _glfw.vk.EXT_metal_surface = GLFW_TRUE; 139b877906bSopenharmony_ci else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0) 140b877906bSopenharmony_ci _glfw.vk.KHR_xlib_surface = GLFW_TRUE; 141b877906bSopenharmony_ci else if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0) 142b877906bSopenharmony_ci _glfw.vk.KHR_xcb_surface = GLFW_TRUE; 143b877906bSopenharmony_ci else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0) 144b877906bSopenharmony_ci _glfw.vk.KHR_wayland_surface = GLFW_TRUE; 145b877906bSopenharmony_ci else if (strcmp(ep[i].extensionName, "VK_EXT_headless_surface") == 0) 146b877906bSopenharmony_ci _glfw.vk.EXT_headless_surface = GLFW_TRUE; 147b877906bSopenharmony_ci } 148b877906bSopenharmony_ci 149b877906bSopenharmony_ci _glfw_free(ep); 150b877906bSopenharmony_ci 151b877906bSopenharmony_ci _glfw.vk.available = GLFW_TRUE; 152b877906bSopenharmony_ci 153b877906bSopenharmony_ci _glfw.platform.getRequiredInstanceExtensions(_glfw.vk.extensions); 154b877906bSopenharmony_ci 155b877906bSopenharmony_ci return GLFW_TRUE; 156b877906bSopenharmony_ci} 157b877906bSopenharmony_ci 158b877906bSopenharmony_civoid _glfwTerminateVulkan(void) 159b877906bSopenharmony_ci{ 160b877906bSopenharmony_ci if (_glfw.vk.handle) 161b877906bSopenharmony_ci _glfwPlatformFreeModule(_glfw.vk.handle); 162b877906bSopenharmony_ci} 163b877906bSopenharmony_ci 164b877906bSopenharmony_ciconst char* _glfwGetVulkanResultString(VkResult result) 165b877906bSopenharmony_ci{ 166b877906bSopenharmony_ci switch (result) 167b877906bSopenharmony_ci { 168b877906bSopenharmony_ci case VK_SUCCESS: 169b877906bSopenharmony_ci return "Success"; 170b877906bSopenharmony_ci case VK_NOT_READY: 171b877906bSopenharmony_ci return "A fence or query has not yet completed"; 172b877906bSopenharmony_ci case VK_TIMEOUT: 173b877906bSopenharmony_ci return "A wait operation has not completed in the specified time"; 174b877906bSopenharmony_ci case VK_EVENT_SET: 175b877906bSopenharmony_ci return "An event is signaled"; 176b877906bSopenharmony_ci case VK_EVENT_RESET: 177b877906bSopenharmony_ci return "An event is unsignaled"; 178b877906bSopenharmony_ci case VK_INCOMPLETE: 179b877906bSopenharmony_ci return "A return array was too small for the result"; 180b877906bSopenharmony_ci case VK_ERROR_OUT_OF_HOST_MEMORY: 181b877906bSopenharmony_ci return "A host memory allocation has failed"; 182b877906bSopenharmony_ci case VK_ERROR_OUT_OF_DEVICE_MEMORY: 183b877906bSopenharmony_ci return "A device memory allocation has failed"; 184b877906bSopenharmony_ci case VK_ERROR_INITIALIZATION_FAILED: 185b877906bSopenharmony_ci return "Initialization of an object could not be completed for implementation-specific reasons"; 186b877906bSopenharmony_ci case VK_ERROR_DEVICE_LOST: 187b877906bSopenharmony_ci return "The logical or physical device has been lost"; 188b877906bSopenharmony_ci case VK_ERROR_MEMORY_MAP_FAILED: 189b877906bSopenharmony_ci return "Mapping of a memory object has failed"; 190b877906bSopenharmony_ci case VK_ERROR_LAYER_NOT_PRESENT: 191b877906bSopenharmony_ci return "A requested layer is not present or could not be loaded"; 192b877906bSopenharmony_ci case VK_ERROR_EXTENSION_NOT_PRESENT: 193b877906bSopenharmony_ci return "A requested extension is not supported"; 194b877906bSopenharmony_ci case VK_ERROR_FEATURE_NOT_PRESENT: 195b877906bSopenharmony_ci return "A requested feature is not supported"; 196b877906bSopenharmony_ci case VK_ERROR_INCOMPATIBLE_DRIVER: 197b877906bSopenharmony_ci return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible"; 198b877906bSopenharmony_ci case VK_ERROR_TOO_MANY_OBJECTS: 199b877906bSopenharmony_ci return "Too many objects of the type have already been created"; 200b877906bSopenharmony_ci case VK_ERROR_FORMAT_NOT_SUPPORTED: 201b877906bSopenharmony_ci return "A requested format is not supported on this device"; 202b877906bSopenharmony_ci case VK_ERROR_SURFACE_LOST_KHR: 203b877906bSopenharmony_ci return "A surface is no longer available"; 204b877906bSopenharmony_ci case VK_SUBOPTIMAL_KHR: 205b877906bSopenharmony_ci return "A swapchain no longer matches the surface properties exactly, but can still be used"; 206b877906bSopenharmony_ci case VK_ERROR_OUT_OF_DATE_KHR: 207b877906bSopenharmony_ci return "A surface has changed in such a way that it is no longer compatible with the swapchain"; 208b877906bSopenharmony_ci case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: 209b877906bSopenharmony_ci return "The display used by a swapchain does not use the same presentable image layout"; 210b877906bSopenharmony_ci case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: 211b877906bSopenharmony_ci return "The requested window is already connected to a VkSurfaceKHR, or to some other non-Vulkan API"; 212b877906bSopenharmony_ci case VK_ERROR_VALIDATION_FAILED_EXT: 213b877906bSopenharmony_ci return "A validation layer found an error"; 214b877906bSopenharmony_ci default: 215b877906bSopenharmony_ci return "ERROR: UNKNOWN VULKAN ERROR"; 216b877906bSopenharmony_ci } 217b877906bSopenharmony_ci} 218b877906bSopenharmony_ci 219b877906bSopenharmony_ci 220b877906bSopenharmony_ci////////////////////////////////////////////////////////////////////////// 221b877906bSopenharmony_ci////// GLFW public API ////// 222b877906bSopenharmony_ci////////////////////////////////////////////////////////////////////////// 223b877906bSopenharmony_ci 224b877906bSopenharmony_ciGLFWAPI int glfwVulkanSupported(void) 225b877906bSopenharmony_ci{ 226b877906bSopenharmony_ci _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); 227b877906bSopenharmony_ci return _glfwInitVulkan(_GLFW_FIND_LOADER); 228b877906bSopenharmony_ci} 229b877906bSopenharmony_ci 230b877906bSopenharmony_ciGLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count) 231b877906bSopenharmony_ci{ 232b877906bSopenharmony_ci assert(count != NULL); 233b877906bSopenharmony_ci 234b877906bSopenharmony_ci *count = 0; 235b877906bSopenharmony_ci 236b877906bSopenharmony_ci _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 237b877906bSopenharmony_ci 238b877906bSopenharmony_ci if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER)) 239b877906bSopenharmony_ci return NULL; 240b877906bSopenharmony_ci 241b877906bSopenharmony_ci if (!_glfw.vk.extensions[0]) 242b877906bSopenharmony_ci return NULL; 243b877906bSopenharmony_ci 244b877906bSopenharmony_ci *count = 2; 245b877906bSopenharmony_ci return (const char**) _glfw.vk.extensions; 246b877906bSopenharmony_ci} 247b877906bSopenharmony_ci 248b877906bSopenharmony_ciGLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, 249b877906bSopenharmony_ci const char* procname) 250b877906bSopenharmony_ci{ 251b877906bSopenharmony_ci GLFWvkproc proc; 252b877906bSopenharmony_ci assert(procname != NULL); 253b877906bSopenharmony_ci 254b877906bSopenharmony_ci _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 255b877906bSopenharmony_ci 256b877906bSopenharmony_ci if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER)) 257b877906bSopenharmony_ci return NULL; 258b877906bSopenharmony_ci 259b877906bSopenharmony_ci // NOTE: Vulkan 1.0 and 1.1 vkGetInstanceProcAddr cannot return itself 260b877906bSopenharmony_ci if (strcmp(procname, "vkGetInstanceProcAddr") == 0) 261b877906bSopenharmony_ci return (GLFWvkproc) vkGetInstanceProcAddr; 262b877906bSopenharmony_ci 263b877906bSopenharmony_ci proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname); 264b877906bSopenharmony_ci if (!proc) 265b877906bSopenharmony_ci { 266b877906bSopenharmony_ci if (_glfw.vk.handle) 267b877906bSopenharmony_ci proc = (GLFWvkproc) _glfwPlatformGetModuleSymbol(_glfw.vk.handle, procname); 268b877906bSopenharmony_ci } 269b877906bSopenharmony_ci 270b877906bSopenharmony_ci return proc; 271b877906bSopenharmony_ci} 272b877906bSopenharmony_ci 273b877906bSopenharmony_ciGLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, 274b877906bSopenharmony_ci VkPhysicalDevice device, 275b877906bSopenharmony_ci uint32_t queuefamily) 276b877906bSopenharmony_ci{ 277b877906bSopenharmony_ci _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); 278b877906bSopenharmony_ci 279b877906bSopenharmony_ci assert(instance != VK_NULL_HANDLE); 280b877906bSopenharmony_ci assert(device != VK_NULL_HANDLE); 281b877906bSopenharmony_ci 282b877906bSopenharmony_ci if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER)) 283b877906bSopenharmony_ci return GLFW_FALSE; 284b877906bSopenharmony_ci 285b877906bSopenharmony_ci if (!_glfw.vk.extensions[0]) 286b877906bSopenharmony_ci { 287b877906bSopenharmony_ci _glfwInputError(GLFW_API_UNAVAILABLE, 288b877906bSopenharmony_ci "Vulkan: Window surface creation extensions not found"); 289b877906bSopenharmony_ci return GLFW_FALSE; 290b877906bSopenharmony_ci } 291b877906bSopenharmony_ci 292b877906bSopenharmony_ci return _glfw.platform.getPhysicalDevicePresentationSupport(instance, 293b877906bSopenharmony_ci device, 294b877906bSopenharmony_ci queuefamily); 295b877906bSopenharmony_ci} 296b877906bSopenharmony_ci 297b877906bSopenharmony_ciGLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, 298b877906bSopenharmony_ci GLFWwindow* handle, 299b877906bSopenharmony_ci const VkAllocationCallbacks* allocator, 300b877906bSopenharmony_ci VkSurfaceKHR* surface) 301b877906bSopenharmony_ci{ 302b877906bSopenharmony_ci assert(surface != NULL); 303b877906bSopenharmony_ci 304b877906bSopenharmony_ci *surface = VK_NULL_HANDLE; 305b877906bSopenharmony_ci 306b877906bSopenharmony_ci _GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED); 307b877906bSopenharmony_ci 308b877906bSopenharmony_ci _GLFWwindow* window = (_GLFWwindow*) handle; 309b877906bSopenharmony_ci assert(window != NULL); 310b877906bSopenharmony_ci assert(instance != VK_NULL_HANDLE); 311b877906bSopenharmony_ci 312b877906bSopenharmony_ci if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER)) 313b877906bSopenharmony_ci return VK_ERROR_INITIALIZATION_FAILED; 314b877906bSopenharmony_ci 315b877906bSopenharmony_ci if (!_glfw.vk.extensions[0]) 316b877906bSopenharmony_ci { 317b877906bSopenharmony_ci _glfwInputError(GLFW_API_UNAVAILABLE, 318b877906bSopenharmony_ci "Vulkan: Window surface creation extensions not found"); 319b877906bSopenharmony_ci return VK_ERROR_EXTENSION_NOT_PRESENT; 320b877906bSopenharmony_ci } 321b877906bSopenharmony_ci 322b877906bSopenharmony_ci if (window->context.client != GLFW_NO_API) 323b877906bSopenharmony_ci { 324b877906bSopenharmony_ci _glfwInputError(GLFW_INVALID_VALUE, 325b877906bSopenharmony_ci "Vulkan: Window surface creation requires the window to have the client API set to GLFW_NO_API"); 326b877906bSopenharmony_ci return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR; 327b877906bSopenharmony_ci } 328b877906bSopenharmony_ci 329b877906bSopenharmony_ci return _glfw.platform.createWindowSurface(instance, window, allocator, surface); 330b877906bSopenharmony_ci} 331b877906bSopenharmony_ci 332