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