Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/openxr/src/loader/loader_platform.hpp
9917 views
1
// Copyright (c) 2017-2025 The Khronos Group Inc.
2
// Copyright (c) 2017-2019 Valve Corporation
3
// Copyright (c) 2017-2019 LunarG, Inc.
4
//
5
// SPDX-License-Identifier: Apache-2.0 OR MIT
6
//
7
// Initial Authors: Mark Young <[email protected]>, Dave Houlton <[email protected]>
8
//
9
10
#pragma once
11
12
#include <cassert>
13
#include <sstream>
14
#include <string>
15
16
#include "xr_dependencies.h"
17
#include "platform_utils.hpp"
18
19
#if defined(__GNUC__) && __GNUC__ >= 4
20
#define LOADER_EXPORT __attribute__((visibility("default")))
21
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
22
#define LOADER_EXPORT __attribute__((visibility("default")))
23
#else
24
#define LOADER_EXPORT
25
#endif
26
27
// Environment variables
28
#if defined(XR_OS_LINUX) || defined(XR_OS_APPLE) || defined(XR_OS_ANDROID)
29
30
#include <sys/types.h>
31
#include <sys/stat.h>
32
#include <dlfcn.h>
33
#include <unistd.h>
34
#include <stdlib.h>
35
#include <dirent.h>
36
37
#ifndef PATH_MAX
38
#define PATH_MAX 1024
39
#endif
40
41
#define PATH_SEPARATOR ':'
42
#define DIRECTORY_SYMBOL '/'
43
44
// Dynamic Loading of libraries:
45
typedef void *LoaderPlatformLibraryHandle;
46
static inline LoaderPlatformLibraryHandle LoaderPlatformLibraryOpen(const std::string &path) {
47
// When loading the library, we use RTLD_LAZY so that not all symbols have to be
48
// resolved at this time (which improves performance). Note that if not all symbols
49
// can be resolved, this could cause crashes later.
50
// For experimenting/debugging: Define the LD_BIND_NOW environment variable to force all
51
// symbols to be resolved here.
52
return dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL);
53
}
54
55
static inline const char *LoaderPlatformLibraryOpenError(const std::string &path) {
56
(void)path;
57
return dlerror();
58
}
59
60
static inline void LoaderPlatformLibraryClose(LoaderPlatformLibraryHandle library) { dlclose(library); }
61
62
static inline void *LoaderPlatformLibraryGetProcAddr(LoaderPlatformLibraryHandle library, const std::string &name) {
63
assert(library);
64
assert(!name.empty());
65
return dlsym(library, name.c_str());
66
}
67
68
static inline const char *LoaderPlatformLibraryGetProcAddrError(const std::string &name) {
69
(void)name;
70
return dlerror();
71
}
72
73
#elif defined(XR_OS_WINDOWS)
74
75
#define PATH_SEPARATOR ';'
76
#define DIRECTORY_SYMBOL '\\'
77
78
// Workaround for MS VS 2010/2013 missing snprintf and vsnprintf
79
#if defined(_MSC_VER) && _MSC_VER < 1900
80
#include <stdint.h>
81
82
static inline int32_t xr_vsnprintf(char *result_buffer, size_t buffer_size, const char *print_format, va_list varying_list) {
83
int32_t copy_count = -1;
84
if (buffer_size != 0) {
85
copy_count = _vsnprintf_s(result_buffer, buffer_size, _TRUNCATE, print_format, varying_list);
86
}
87
if (copy_count == -1) {
88
copy_count = _vscprintf(print_format, varying_list);
89
}
90
return copy_count;
91
}
92
93
static inline int32_t xr_snprintf(char *result_buffer, size_t buffer_size, const char *print_format, ...) {
94
va_list varying_list;
95
va_start(varying_list, print_format);
96
int32_t copy_count = xr_vsnprintf(result_buffer, buffer_size, print_format, varying_list);
97
va_end(varying_list);
98
return copy_count;
99
}
100
101
#define snprintf xr_snprintf
102
#define vsnprintf xr_vsnprintf
103
104
#endif
105
106
static inline std::string DescribeError(uint32_t code, bool prefixErrorCode = true) {
107
std::string str;
108
109
if (prefixErrorCode) {
110
char prefixBuffer[64];
111
snprintf(prefixBuffer, sizeof(prefixBuffer), "0x%llx (%lld): ", (uint64_t)code, (int64_t)code);
112
str = prefixBuffer;
113
}
114
115
// Could use FORMAT_MESSAGE_FROM_HMODULE to specify an error source.
116
WCHAR errorBufferW[1024]{};
117
const DWORD errorBufferWCapacity = sizeof(errorBufferW) / sizeof(errorBufferW[0]);
118
const DWORD length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, (DWORD)code,
119
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errorBufferW, errorBufferWCapacity, nullptr);
120
121
if (length) { // If errorBufferW contains what we are looking for...
122
str += wide_to_utf8(errorBufferW);
123
} else {
124
str = "(unknown)";
125
}
126
127
return str;
128
}
129
130
// Dynamic Loading:
131
typedef HMODULE LoaderPlatformLibraryHandle;
132
static inline LoaderPlatformLibraryHandle LoaderPlatformLibraryOpen(const std::string &path) {
133
const std::wstring pathW = utf8_to_wide(path);
134
135
// Try loading the library the original way first.
136
LoaderPlatformLibraryHandle handle = LoadLibraryW(pathW.c_str());
137
138
if (handle == NULL && GetLastError() == ERROR_MOD_NOT_FOUND) {
139
const DWORD dwAttrib = GetFileAttributesW(pathW.c_str());
140
const bool fileExists = (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
141
if (fileExists) {
142
// If that failed, then try loading it with broader search folders.
143
handle = LoadLibraryExW(pathW.c_str(), NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
144
}
145
}
146
147
return handle;
148
}
149
150
static inline std::string LoaderPlatformLibraryOpenError(const std::string &path) {
151
std::stringstream ss;
152
const DWORD dwLastError = GetLastError();
153
const std::string strError = DescribeError(dwLastError);
154
ss << "Failed to open dynamic library " << path << " with error " << dwLastError << ": " << strError;
155
return ss.str();
156
}
157
158
static inline void LoaderPlatformLibraryClose(LoaderPlatformLibraryHandle library) { FreeLibrary(library); }
159
160
static inline void *LoaderPlatformLibraryGetProcAddr(LoaderPlatformLibraryHandle library, const std::string &name) {
161
assert(library);
162
assert(name.size() > 0);
163
return reinterpret_cast<void *>(GetProcAddress(library, name.c_str()));
164
}
165
166
static inline std::string LoaderPlatformLibraryGetProcAddrAddrError(const std::string &name) {
167
std::stringstream ss;
168
ss << "Failed to find function " << name << " in dynamic library";
169
return ss.str();
170
}
171
172
#else // Not Linux or Windows
173
174
#define PATH_SEPARATOR ':'
175
#define DIRECTORY_SYMBOL '/'
176
177
static inline LoaderPlatformLibraryHandle LoaderPlatformLibraryOpen(const std::string &path) {
178
// Stub func
179
#error("Unknown platform, undefined dynamic library routines resulting");
180
(void)path;
181
}
182
183
static inline const char *LoaderPlatformLibraryOpenError(const std::string &path) {
184
// Stub func
185
(void)path;
186
}
187
188
static inline void LoaderPlatformLibraryClose(LoaderPlatformLibraryHandle library) {
189
// Stub func
190
(void)library;
191
}
192
193
static inline void *LoaderPlatformLibraryGetProcAddr(LoaderPlatformLibraryHandle library, const std::string &name) {
194
// Stub func
195
void(library);
196
void(name);
197
}
198
199
static inline const char *LoaderPlatformLibraryGetProcAddrError(const std::string &name) {
200
// Stub func
201
(void)name;
202
}
203
204
#endif
205
206