1 | /* |
2 | Simple DirectMedia Layer |
3 | Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org> |
4 | |
5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. |
8 | |
9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: |
12 | |
13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ |
21 | |
22 | /* |
23 | * @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's |
24 | * SDL_x11vulkan.c. |
25 | */ |
26 | |
27 | #include "../../SDL_internal.h" |
28 | |
29 | #if SDL_VIDEO_VULKAN && SDL_VIDEO_DRIVER_WAYLAND |
30 | |
31 | #include "SDL_waylandvideo.h" |
32 | #include "SDL_waylandwindow.h" |
33 | |
34 | #include "SDL_loadso.h" |
35 | #include "SDL_waylandvulkan.h" |
36 | #include "SDL_syswm.h" |
37 | |
38 | #if defined(__OpenBSD__) |
39 | #define DEFAULT_VULKAN "libvulkan.so" |
40 | #else |
41 | #define DEFAULT_VULKAN "libvulkan.so.1" |
42 | #endif |
43 | |
44 | int Wayland_Vulkan_LoadLibrary(_THIS, const char *path) |
45 | { |
46 | VkExtensionProperties *extensions = NULL; |
47 | Uint32 i, extensionCount = 0; |
48 | SDL_bool hasSurfaceExtension = SDL_FALSE; |
49 | SDL_bool hasWaylandSurfaceExtension = SDL_FALSE; |
50 | PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL; |
51 | if(_this->vulkan_config.loader_handle) |
52 | return SDL_SetError("Vulkan already loaded" ); |
53 | |
54 | /* Load the Vulkan loader library */ |
55 | if(!path) |
56 | path = SDL_getenv("SDL_VULKAN_LIBRARY" ); |
57 | if(!path) |
58 | path = DEFAULT_VULKAN; |
59 | _this->vulkan_config.loader_handle = SDL_LoadObject(path); |
60 | if(!_this->vulkan_config.loader_handle) |
61 | return -1; |
62 | SDL_strlcpy(_this->vulkan_config.loader_path, path, |
63 | SDL_arraysize(_this->vulkan_config.loader_path)); |
64 | vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction( |
65 | _this->vulkan_config.loader_handle, "vkGetInstanceProcAddr" ); |
66 | if(!vkGetInstanceProcAddr) |
67 | goto fail; |
68 | _this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr; |
69 | _this->vulkan_config.vkEnumerateInstanceExtensionProperties = |
70 | (void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)( |
71 | VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties" ); |
72 | if(!_this->vulkan_config.vkEnumerateInstanceExtensionProperties) |
73 | goto fail; |
74 | extensions = SDL_Vulkan_CreateInstanceExtensionsList( |
75 | (PFN_vkEnumerateInstanceExtensionProperties) |
76 | _this->vulkan_config.vkEnumerateInstanceExtensionProperties, |
77 | &extensionCount); |
78 | if(!extensions) |
79 | goto fail; |
80 | for(i = 0; i < extensionCount; i++) |
81 | { |
82 | if(SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) |
83 | hasSurfaceExtension = SDL_TRUE; |
84 | else if(SDL_strcmp(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) |
85 | hasWaylandSurfaceExtension = SDL_TRUE; |
86 | } |
87 | SDL_free(extensions); |
88 | if(!hasSurfaceExtension) |
89 | { |
90 | SDL_SetError("Installed Vulkan doesn't implement the " |
91 | VK_KHR_SURFACE_EXTENSION_NAME " extension" ); |
92 | goto fail; |
93 | } |
94 | else if(!hasWaylandSurfaceExtension) |
95 | { |
96 | SDL_SetError("Installed Vulkan doesn't implement the " |
97 | VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME "extension" ); |
98 | goto fail; |
99 | } |
100 | return 0; |
101 | |
102 | fail: |
103 | SDL_UnloadObject(_this->vulkan_config.loader_handle); |
104 | _this->vulkan_config.loader_handle = NULL; |
105 | return -1; |
106 | } |
107 | |
108 | void Wayland_Vulkan_UnloadLibrary(_THIS) |
109 | { |
110 | if(_this->vulkan_config.loader_handle) |
111 | { |
112 | SDL_UnloadObject(_this->vulkan_config.loader_handle); |
113 | _this->vulkan_config.loader_handle = NULL; |
114 | } |
115 | } |
116 | |
117 | SDL_bool Wayland_Vulkan_GetInstanceExtensions(_THIS, |
118 | SDL_Window *window, |
119 | unsigned *count, |
120 | const char **names) |
121 | { |
122 | static const char *const extensionsForWayland[] = { |
123 | VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME |
124 | }; |
125 | if(!_this->vulkan_config.loader_handle) |
126 | { |
127 | SDL_SetError("Vulkan is not loaded" ); |
128 | return SDL_FALSE; |
129 | } |
130 | return SDL_Vulkan_GetInstanceExtensions_Helper( |
131 | count, names, SDL_arraysize(extensionsForWayland), |
132 | extensionsForWayland); |
133 | } |
134 | |
135 | void Wayland_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h) |
136 | { |
137 | SDL_WindowData *data; |
138 | if (window->driverdata) { |
139 | data = (SDL_WindowData *) window->driverdata; |
140 | |
141 | if (w) { |
142 | *w = window->w * data->scale_factor; |
143 | } |
144 | |
145 | if (h) { |
146 | *h = window->h * data->scale_factor; |
147 | } |
148 | } |
149 | } |
150 | |
151 | SDL_bool Wayland_Vulkan_CreateSurface(_THIS, |
152 | SDL_Window *window, |
153 | VkInstance instance, |
154 | VkSurfaceKHR *surface) |
155 | { |
156 | SDL_WindowData *windowData = (SDL_WindowData *)window->driverdata; |
157 | PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = |
158 | (PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr; |
159 | PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR = |
160 | (PFN_vkCreateWaylandSurfaceKHR)vkGetInstanceProcAddr( |
161 | instance, |
162 | "vkCreateWaylandSurfaceKHR" ); |
163 | VkWaylandSurfaceCreateInfoKHR createInfo; |
164 | VkResult result; |
165 | |
166 | if(!_this->vulkan_config.loader_handle) |
167 | { |
168 | SDL_SetError("Vulkan is not loaded" ); |
169 | return SDL_FALSE; |
170 | } |
171 | |
172 | if(!vkCreateWaylandSurfaceKHR) |
173 | { |
174 | SDL_SetError(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME |
175 | " extension is not enabled in the Vulkan instance." ); |
176 | return SDL_FALSE; |
177 | } |
178 | SDL_zero(createInfo); |
179 | createInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR; |
180 | createInfo.pNext = NULL; |
181 | createInfo.flags = 0; |
182 | createInfo.display = windowData->waylandData->display; |
183 | createInfo.surface = windowData->surface; |
184 | result = vkCreateWaylandSurfaceKHR(instance, &createInfo, |
185 | NULL, surface); |
186 | if(result != VK_SUCCESS) |
187 | { |
188 | SDL_SetError("vkCreateWaylandSurfaceKHR failed: %s" , |
189 | SDL_Vulkan_GetResultString(result)); |
190 | return SDL_FALSE; |
191 | } |
192 | return SDL_TRUE; |
193 | } |
194 | |
195 | #endif |
196 | |
197 | /* vim: set ts=4 sw=4 expandtab: */ |
198 | |