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