blob: f79a61d4aba5b7fe0143d4eb8bdde60e7c87faf8 [file] [log] [blame]
Ian Elliott81ac44c2015-01-13 17:52:38 -07001/*
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06002 * Vulkan
Ian Elliott81ac44c2015-01-13 17:52:38 -07003 *
4 * Copyright (C) 2015 LunarG, Inc.
5 * Copyright 2014 Valve Software
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
Jon Ashburnffd5d672015-06-29 11:25:34 -060027 * Jon Ashburn <jon@luanrg.com>
Ian Elliott81ac44c2015-01-13 17:52:38 -070028 * Ian Elliott <ian@lunarg.com>
29 */
30
31#ifndef LOADER_PLATFORM_H
32#define LOADER_PLATFORM_H
33
Cody Northrop62ac1c52015-07-08 16:48:37 -060034#include "vk_platform.h"
35
Ian Elliott81ac44c2015-01-13 17:52:38 -070036#if defined(__linux__)
37/* Linux-specific common code: */
38
39// Headers:
40//#define _GNU_SOURCE 1
41// TBD: Are the contents of the following file used?
42#include <unistd.h>
43// Note: The following file is for dynamic loading:
44#include <dlfcn.h>
45#include <pthread.h>
46#include <assert.h>
Jon Ashburnffd5d672015-06-29 11:25:34 -060047#include <stdbool.h>
Jon Ashburn38144502015-07-07 15:06:25 -060048#include <libgen.h>
Ian Elliott81ac44c2015-01-13 17:52:38 -070049
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060050// VK Library Filenames, Paths, etc.:
Ian Elliott665c5632015-02-04 11:22:39 -070051#define PATH_SEPERATOR ':'
Jon Ashburnffd5d672015-06-29 11:25:34 -060052#define DIRECTORY_SYMBOL '/'
53
Adam Jackson05487a22015-07-23 16:29:26 -040054#define DEFAULT_VK_DRIVERS_INFO \
55 SYSCONFDIR "/vulkan/icd.d:" \
56 DATADIR "/vulkan/icd.d"
57#define DEFAULT_VK_DRIVERS_PATH \
58 LIBDIR "/vulkan/icd"
59#define DEFAULT_VK_LAYERS_INFO \
60 SYSCONFDIR "/vulkan/explicit_layer.d:" \
61 SYSCONFDIR "/vulkan/implicit_layer.d:" \
62 DATADIR "/vulkan/explicit_layer.d:" \
63 DATADIR "/vulkan/implicit_layer.d"
64#define DEFAULT_VK_LAYERS_PATH \
65 LIBDIR "/vulkan/layer"
Jon Ashburn1b111de2015-07-06 15:40:35 -060066#define LAYERS_PATH_ENV "VK_LAYER_DIRS"
Ian Elliott665c5632015-02-04 11:22:39 -070067
Ian Elliottecb60ec2015-02-12 16:44:56 -070068// C99:
Tobin Ehlisbf0146e2015-02-11 14:24:02 -070069#define PRINTF_SIZE_T_SPECIFIER "%zu"
70
Jon Ashburnffd5d672015-06-29 11:25:34 -060071// File IO
72static inline bool loader_platform_file_exists(const char *path)
73{
74 if (access(path, F_OK))
75 return false;
76 else
77 return true;
78}
79
Jon Ashburn38144502015-07-07 15:06:25 -060080static inline bool loader_platform_is_path_absolute(const char *path)
81{
82 if (path[0] == '/')
83 return true;
84 else
85 return false;
86}
87
88static inline char *loader_platform_dirname(char *path)
89{
90 return dirname(path);
91}
92
Jon Ashburnffd5d672015-06-29 11:25:34 -060093// Dynamic Loading of libraries:
Ian Elliott81ac44c2015-01-13 17:52:38 -070094typedef void * loader_platform_dl_handle;
95static inline loader_platform_dl_handle loader_platform_open_library(const char* libPath)
96{
Chia-I Wu7397c432015-02-18 14:39:54 -070097 return dlopen(libPath, RTLD_LAZY | RTLD_LOCAL);
Ian Elliott81ac44c2015-01-13 17:52:38 -070098}
99static inline char * loader_platform_open_library_error(const char* libPath)
100{
101 return dlerror();
102}
103static inline void loader_platform_close_library(loader_platform_dl_handle library)
104{
105 dlclose(library);
106}
107static inline void * loader_platform_get_proc_address(loader_platform_dl_handle library,
108 const char *name)
109{
110 assert(library);
111 assert(name);
112 return dlsym(library, name);
113}
114static inline char * loader_platform_get_proc_address_error(const char *name)
115{
116 return dlerror();
117}
118
119// Threads:
120typedef pthread_t loader_platform_thread;
121#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \
122 pthread_once_t var = PTHREAD_ONCE_INIT;
Jon Ashburnfce93d92015-05-12 17:26:48 -0600123#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) \
124 pthread_once_t var;
Ian Elliott81ac44c2015-01-13 17:52:38 -0700125static inline void loader_platform_thread_once(void *ctl, void (* func) (void))
126{
127 assert(func != NULL);
128 assert(ctl != NULL);
129 pthread_once((pthread_once_t *) ctl, func);
130}
131
132// Thread IDs:
133typedef pthread_t loader_platform_thread_id;
134static inline loader_platform_thread_id loader_platform_get_thread_id()
135{
136 return pthread_self();
137}
138
139// Thread mutex:
140typedef pthread_mutex_t loader_platform_thread_mutex;
141static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex* pMutex)
142{
143 pthread_mutex_init(pMutex, NULL);
144}
145static inline void loader_platform_thread_lock_mutex(loader_platform_thread_mutex* pMutex)
146{
147 pthread_mutex_lock(pMutex);
148}
149static inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex* pMutex)
150{
151 pthread_mutex_unlock(pMutex);
152}
153static inline void loader_platform_thread_delete_mutex(loader_platform_thread_mutex* pMutex)
154{
155 pthread_mutex_destroy(pMutex);
156}
Mike Stroyan354ed672015-05-15 08:50:57 -0600157typedef pthread_cond_t loader_platform_thread_cond;
158static inline void loader_platform_thread_init_cond(loader_platform_thread_cond* pCond)
159{
160 pthread_cond_init(pCond, NULL);
161}
162static inline void loader_platform_thread_cond_wait(loader_platform_thread_cond* pCond, loader_platform_thread_mutex* pMutex)
163{
164 pthread_cond_wait(pCond, pMutex);
165}
166static inline void loader_platform_thread_cond_broadcast(loader_platform_thread_cond* pCond)
167{
168 pthread_cond_broadcast(pCond);
169}
Ian Elliott81ac44c2015-01-13 17:52:38 -0700170
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600171#define loader_stack_alloc(size) alloca(size)
172static inline void *loader_aligned_alloc(size_t alignment, size_t size) { return aligned_alloc(alignment, size); }
Ian Elliott81ac44c2015-01-13 17:52:38 -0700173
174#elif defined(_WIN32) // defined(__linux__)
175/* Windows-specific common code: */
176
177// Headers:
Piers Danielle2bca482015-02-24 13:58:47 -0700178#include <WinSock2.h>
Ian Elliott81ac44c2015-01-13 17:52:38 -0700179#include <windows.h>
180#include <assert.h>
Tony Barbour69698512015-06-18 16:29:32 -0600181#include <stdio.h>
Jon Ashburnee33ae72015-06-30 14:46:22 -0700182#include <io.h>
183#include <stdbool.h>
Cody Northrop62ac1c52015-07-08 16:48:37 -0600184#include <shlwapi.h>
Ian Elliott81ac44c2015-01-13 17:52:38 -0700185#ifdef __cplusplus
186#include <iostream>
187#include <string>
188using namespace std;
189#endif // __cplusplus
190
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600191// VK Library Filenames, Paths, etc.:
Ian Elliott665c5632015-02-04 11:22:39 -0700192#define PATH_SEPERATOR ';'
Jon Ashburnffd5d672015-06-29 11:25:34 -0600193#define DIRECTORY_SYMBOL '\\'
Jon Ashburnee33ae72015-06-30 14:46:22 -0700194#define DEFAULT_VK_REGISTRY_HIVE HKEY_LOCAL_MACHINE
195#define DEFAULT_VK_DRIVERS_INFO "SOFTWARE\\Khronos\\Vulkan\\Drivers"
Jon Ashburnffd5d672015-06-29 11:25:34 -0600196// TODO: Are these the correct paths
scygan8420b4c2015-06-01 19:47:08 +0200197#define DEFAULT_VK_DRIVERS_PATH "C:\\Windows\\System32;C:\\Windows\\SysWow64"
Jon Ashburn1b111de2015-07-06 15:40:35 -0600198#define DEFAULT_VK_LAYERS_INFO "SOFTWARE\\Khronos\\Vulkan\\ExplicitLayers;SOFTWARE\\Khronos\\Vulkan\\ImplicitLayers"
Jon Ashburn38144502015-07-07 15:06:25 -0600199#define DEFAULT_VK_LAYERS_PATH "C:\\Windows\\System32;C:\\Windows\\SysWow64"
Jon Ashburncfcd6132015-07-23 18:58:21 -0600200#define LAYERS_PATH_ENV "VK_LAYER_FOLDERS"
Ian Elliott665c5632015-02-04 11:22:39 -0700201
Ian Elliott81ac44c2015-01-13 17:52:38 -0700202// C99:
203// Microsoft didn't implement C99 in Visual Studio; but started adding it with
204// VS2013. However, VS2013 still didn't have snprintf(). The following is a
Ian Elliott64f74a82015-02-04 12:06:46 -0700205// work-around (Note: The _CRT_SECURE_NO_WARNINGS macro must be set in the
206// "CMakeLists.txt" file).
Ian Elliott81ac44c2015-01-13 17:52:38 -0700207#define snprintf _snprintf
Jon Ashburn38144502015-07-07 15:06:25 -0600208#define strdup _strdup
Tobin Ehlisbf0146e2015-02-11 14:24:02 -0700209#define PRINTF_SIZE_T_SPECIFIER "%Iu"
David Pinedo3053c672015-07-02 09:04:37 -0600210
David Pinedo3053c672015-07-02 09:04:37 -0600211
Jon Ashburnffd5d672015-06-29 11:25:34 -0600212// File IO
Jon Ashburnee33ae72015-06-30 14:46:22 -0700213static bool loader_platform_file_exists(const char *path)
Jon Ashburnffd5d672015-06-29 11:25:34 -0600214{
Jon Ashburnee33ae72015-06-30 14:46:22 -0700215 if ((_access(path, 0)) == -1)
Jon Ashburnffd5d672015-06-29 11:25:34 -0600216 return false;
217 else
218 return true;
219}
220
Cody Northrop62ac1c52015-07-08 16:48:37 -0600221static bool loader_platform_is_path_absolute(const char *path)
Jon Ashburn38144502015-07-07 15:06:25 -0600222{
223 return !PathIsRelative(path);
224}
225
226// WIN32 runtime doesn't have dirname().
227static inline char *loader_platform_dirname(char *path)
228{
229 char *current, *next;
230
231 // TODO/TBD: Do we need to deal with the Windows's ":" character?
232
233 for (current = path; *current != '\0'; current = next) {
234 next = strchr(current, DIRECTORY_SYMBOL);
235 if (next == NULL) {
236 if (current != path)
237 *(current - 1) = '\0';
238 return path;
239 } else {
240 // Point one character past the DIRECTORY_SYMBOL:
241 next++;
242 }
243 }
244 return path;
245}
246
247// WIN32 runtime doesn't have basename().
248// Microsoft also doesn't have basename(). Paths are different on Windows, and
249// so this is just a temporary solution in order to get us compiling, so that we
250// can test some scenarios, and develop the correct solution for Windows.
251 // TODO: Develop a better, permanent solution for Windows, to replace this
252 // temporary code:
253static char *loader_platform_basename(char *pathname)
254{
255 char *current, *next;
256
257// TODO/TBD: Do we need to deal with the Windows's ":" character?
258
259 for (current = pathname; *current != '\0'; current = next) {
260 next = strchr(current, DIRECTORY_SYMBOL);
261 if (next == NULL) {
262 // No more DIRECTORY_SYMBOL's so return p:
263 return current;
264 } else {
265 // Point one character past the DIRECTORY_SYMBOL:
266 next++;
267 }
268 }
269 // We shouldn't get to here, but this makes the compiler happy:
270 return current;
271}
272
Ian Elliott81ac44c2015-01-13 17:52:38 -0700273// Dynamic Loading:
274typedef HMODULE loader_platform_dl_handle;
275static loader_platform_dl_handle loader_platform_open_library(const char* libPath)
276{
277 return LoadLibrary(libPath);
278}
279static char * loader_platform_open_library_error(const char* libPath)
280{
281 static char errorMsg[120];
282 snprintf(errorMsg, 119, "Failed to open dynamic library \"%s\"", libPath);
283 return errorMsg;
284}
285static void loader_platform_close_library(loader_platform_dl_handle library)
286{
287 FreeLibrary(library);
288}
289static void * loader_platform_get_proc_address(loader_platform_dl_handle library,
290 const char *name)
291{
292 assert(library);
293 assert(name);
294 return GetProcAddress(library, name);
295}
296static char * loader_platform_get_proc_address_error(const char *name)
297{
298 static char errorMsg[120];
299 snprintf(errorMsg, 119, "Failed to find function \"%s\" in dynamic library", name);
300 return errorMsg;
301}
302
303// Threads:
304typedef HANDLE loader_platform_thread;
305#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \
306 INIT_ONCE var = INIT_ONCE_STATIC_INIT;
Jon Ashburnfce93d92015-05-12 17:26:48 -0600307#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) \
308 INIT_ONCE var;
Piers Daniell886be472015-02-23 16:23:13 -0700309static BOOL CALLBACK InitFuncWrapper(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
310{
311 void (*func)(void) = (void (*)(void))Parameter;
312 func();
313 return TRUE;
314}
315
Ian Elliott81ac44c2015-01-13 17:52:38 -0700316static void loader_platform_thread_once(void *ctl, void (* func) (void))
317{
318 assert(func != NULL);
319 assert(ctl != NULL);
Piers Daniell886be472015-02-23 16:23:13 -0700320 InitOnceExecuteOnce((PINIT_ONCE) ctl, InitFuncWrapper, func, NULL);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700321}
322
323// Thread IDs:
324typedef DWORD loader_platform_thread_id;
325static loader_platform_thread_id loader_platform_get_thread_id()
326{
327 return GetCurrentThreadId();
328}
329
330// Thread mutex:
331typedef CRITICAL_SECTION loader_platform_thread_mutex;
332static void loader_platform_thread_create_mutex(loader_platform_thread_mutex* pMutex)
333{
334 InitializeCriticalSection(pMutex);
335}
336static void loader_platform_thread_lock_mutex(loader_platform_thread_mutex* pMutex)
337{
338 EnterCriticalSection(pMutex);
339}
340static void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex* pMutex)
341{
342 LeaveCriticalSection(pMutex);
343}
344static void loader_platform_thread_delete_mutex(loader_platform_thread_mutex* pMutex)
345{
346 DeleteCriticalSection(pMutex);
347}
Mike Stroyan33053d02015-05-15 17:34:51 -0600348typedef CONDITION_VARIABLE loader_platform_thread_cond;
349static void loader_platform_thread_init_cond(loader_platform_thread_cond* pCond)
350{
351 InitializeConditionVariable(pCond);
352}
353static void loader_platform_thread_cond_wait(loader_platform_thread_cond* pCond, loader_platform_thread_mutex* pMutex)
354{
355 SleepConditionVariableCS(pCond, pMutex, INFINITE);
356}
357static void loader_platform_thread_cond_broadcast(loader_platform_thread_cond* pCond)
358{
359 WakeAllConditionVariable(pCond);
360}
Ian Elliott81ac44c2015-01-13 17:52:38 -0700361
Ian Elliott76005132015-03-31 15:32:41 -0600362// Windows Registry:
363char *loader_get_registry_string(const HKEY hive,
364 const LPCTSTR sub_key,
365 const char *value);
366
Ian Elliott81ac44c2015-01-13 17:52:38 -0700367#else // defined(_WIN32)
368
369#error The "loader_platform.h" file must be modified for this OS.
370
371// NOTE: In order to support another OS, an #elif needs to be added (above the
372// "#else // defined(_WIN32)") for that OS, and OS-specific versions of the
373// contents of this file must be created.
374
375// NOTE: Other OS-specific changes are also needed for this OS. Search for
376// files with "WIN32" in it, as a quick way to find files that must be changed.
377
378#endif // defined(_WIN32)
379
Ian Elliott20f06872015-02-12 17:08:34 -0700380#else /* LOADER_PLATFORM_H */
381#ifndef LOADER_PLATFORM_H_TEMP
382#define LOADER_PLATFORM_H_TEMP
383
384// NOTE: The following are hopefully-temporary macros to ensure that people
385// don't forget to use the loader_platform_*() functions above:
386
387#if defined(__linux__)
388/* Linux-specific common code: */
389
390// Dynamic Loading:
391#define dlopen PLEASE USE THE loader_platform_open_library() FUNCTION
392#define dlerror PLEASE DO NOT USE THE dlerror() FUNCTION DIRECTLY
393#define dlclose PLEASE USE THE loader_platform_close_library() FUNCTION
394#define dlsym PLEASE USE THE loader_platform_get_proc_address() FUNCTION
395
396// Threads:
397#define pthread_once PLEASE USE THE loader_platform_thread_once() FUNCTION
398#define pthread_self PLEASE USE THE loader_platform_get_thread_id() FUNCTION
399
400// Thread mutex:
401#define pthread_mutex_init PLEASE USE THE loader_platform_thread_create_mutex() FUNCTION
402#define pthread_mutex_lock PLEASE USE THE loader_platform_thread_lock_mutex() FUNCTION
403#define pthread_mutex_unlock PLEASE USE THE loader_platform_thread_unlock_mutex() FUNCTION
404#define pthread_mutex_destroy PLEASE USE THE loader_platform_thread_delete_mutex() FUNCTION
405
406
407#elif defined(_WIN32) // defined(__linux__)
408/* Windows-specific common code: */
409
410// Dynamic Loading:
411//#define LoadLibrary PLEASE USE THE loader_platform_open_library() FUNCTION
412#define FreeLibrary PLEASE USE THE loader_platform_close_library() FUNCTION
413#define GetProcAddress PLEASE USE THE loader_platform_get_proc_address() FUNCTION
414
415// Threads:
416#define InitOnceExecuteOnce PLEASE USE THE loader_platform_thread_once() FUNCTION
417#define GetCurrentThreadId PLEASE USE THE loader_platform_get_thread_id() FUNCTION
418
419// Thread mutex:
420#define InitializeCriticalSection PLEASE USE THE loader_platform_thread_create_mutex() FUNCTION
421#define EnterCriticalSection PLEASE USE THE loader_platform_thread_lock_mutex() FUNCTION
422#define LeaveCriticalSection PLEASE USE THE loader_platform_thread_unlock_mutex() FUNCTION
423#define DeleteCriticalSection PLEASE USE THE loader_platform_thread_delete_mutex() FUNCTION
424
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600425#define loader_stack_alloc(size) _alloca(size)
Cody Northrop62ac1c52015-07-08 16:48:37 -0600426static inline void *loader_aligned_alloc(size_t alignment, size_t size) { return _aligned_malloc(alignment, size); }
Ian Elliott20f06872015-02-12 17:08:34 -0700427
428#endif // defined(_WIN32)
429#endif /* LOADER_PLATFORM_H_TEMP */
Ian Elliott81ac44c2015-01-13 17:52:38 -0700430#endif /* LOADER_PLATFORM_H */