[native] Load glfw via dlopen instead of linking to libglfw

This commit is contained in:
Ethan Lee 2023-12-07 12:44:19 -05:00
parent e97dbfa443
commit 64b9349a37
6 changed files with 86 additions and 26 deletions

View File

@ -55,14 +55,14 @@ namespace dxvk::wsi {
return false;
int32_t displayCount = 0;
GLFWmonitor** monitors = glfwGetMonitors(&displayCount);
GLFWmonitor** monitors = WsiLibrary::get()->glfwGetMonitors(&displayCount);
GLFWmonitor* monitor = monitors[displayId];
int32_t x;
int32_t y;
int32_t w;
int32_t h;
glfwGetMonitorWorkarea(monitor, &x, &y, &w, &h);
WsiLibrary::get()->glfwGetMonitorWorkarea(monitor, &x, &y, &w, &h);
pRect->left = x;
pRect->top = y;
@ -103,14 +103,14 @@ namespace dxvk::wsi {
WsiMode* pMode) {
const int32_t displayId = fromHmonitor(hMonitor);
int32_t displayCount = 0;
GLFWmonitor** monitors = glfwGetMonitors(&displayCount);
GLFWmonitor** monitors = WsiLibrary::get()->glfwGetMonitors(&displayCount);
GLFWmonitor* monitor = monitors[displayId];
if (!isDisplayValid(displayId))
return false;
int32_t count = 0;
const GLFWvidmode* modes = glfwGetVideoModes(monitor, &count);
const GLFWvidmode* modes = WsiLibrary::get()->glfwGetVideoModes(monitor, &count);
if(ModeNumber >= uint32_t(count))
return false;
@ -130,10 +130,10 @@ namespace dxvk::wsi {
return false;
int32_t displayCount = 0;
GLFWmonitor** monitors = glfwGetMonitors(&displayCount);
GLFWmonitor** monitors = WsiLibrary::get()->glfwGetMonitors(&displayCount);
GLFWmonitor* monitor = monitors[displayId];
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
const GLFWvidmode* mode = WsiLibrary::get()->glfwGetVideoMode(monitor);
convertMode(*mode, pMode);
@ -150,11 +150,11 @@ namespace dxvk::wsi {
return false;
int32_t displayCount = 0;
GLFWmonitor** monitors = glfwGetMonitors(&displayCount);
GLFWmonitor** monitors = WsiLibrary::get()->glfwGetMonitors(&displayCount);
GLFWmonitor* monitor = monitors[displayId];
//TODO: actually implement this properly, currently we just grab the current one
convertMode(*glfwGetVideoMode(monitor), pMode);
convertMode(*WsiLibrary::get()->glfwGetVideoMode(monitor), pMode);
return true;
}

View File

@ -0,0 +1,34 @@
#include "wsi_platform_glfw.h"
#include "../util/util_win32_compat.h"
namespace dxvk::wsi {
WsiLibrary *WsiLibrary::s_instance = nullptr;
WsiLibrary *WsiLibrary::get() {
if (s_instance != nullptr)
return s_instance;
s_instance = new WsiLibrary();
// FIXME: When do we free this...?
s_instance->libglfw = LoadLibraryA( // FIXME: Get soname as string from meson
#if defined(_WIN32)
"glfw.dll"
#elif defined(__APPLE__)
"libglfw.3.dylib"
#else
"libglfw.so.3"
#endif
);
if (s_instance->libglfw == nullptr)
throw DxvkError("GLFW WSI: Failed to load GLFW DLL.");
#define GLFW_PROC(ret, name, params) \
s_instance->name = reinterpret_cast<pfn_##name>(GetProcAddress(s_instance->libglfw, #name)); \
if (s_instance->name == nullptr) \
throw DxvkError("GLFW WSI: Failed to load " #name ".");
#include "wsi_platform_glfw_funcs.h"
return s_instance;
}
}

View File

@ -12,12 +12,27 @@ namespace dxvk::wsi {
*/
struct DxvkWindowState {
};
struct WsiLibrary {
private:
static WsiLibrary *s_instance;
HMODULE libglfw;
public:
static WsiLibrary *get();
#define GLFW_PROC(ret, name, params) \
typedef ret (*pfn_##name) params; \
pfn_##name name;
#include "wsi_platform_glfw_funcs.h"
};
inline bool isDisplayValid(int32_t displayId) {
int32_t displayCount = 0;
glfwGetMonitors(&displayCount);
WsiLibrary::get()->glfwGetMonitors(&displayCount);
return displayId < displayCount && displayId >= 0;
}
}
}

View File

@ -0,0 +1,12 @@
GLFW_PROC(VkResult, glfwCreateWindowSurface, (VkInstance, GLFWwindow*, const VkAllocationCallbacks*, VkSurfaceKHR*))
GLFW_PROC(GLFWmonitor**, glfwGetMonitors, (int*))
GLFW_PROC(void, glfwGetMonitorWorkarea, (GLFWmonitor*, int*, int*, int*, int*))
GLFW_PROC(GLFWmonitor*, glfwGetPrimaryMonitor, (void))
GLFW_PROC(const char**, glfwGetRequiredInstanceExtensions, (uint32_t*))
GLFW_PROC(const GLFWvidmode*, glfwGetVideoMode, (GLFWmonitor*))
GLFW_PROC(const GLFWvidmode*, glfwGetVideoModes, (GLFWmonitor*, int*))
GLFW_PROC(void, glfwGetWindowSize, (GLFWwindow*, int*, int*))
GLFW_PROC(void, glfwSetWindowMonitor, (GLFWwindow*, GLFWmonitor*, int, int, int, int, int))
GLFW_PROC(void, glfwSetWindowSize, (GLFWwindow*, int, int))
GLFW_PROC(int, glfwVulkanSupported, (void))
#undef GLFW_PROC

View File

@ -19,7 +19,7 @@ namespace dxvk::wsi {
GLFWwindow* window = fromHwnd(hWindow);
int32_t w, h;
glfwGetWindowSize(window, &w, &h);
WsiLibrary::get()->glfwGetWindowSize(window, &w, &h);
if (pWidth)
*pWidth = uint32_t(w);
@ -36,7 +36,7 @@ namespace dxvk::wsi {
uint32_t Height) {
GLFWwindow* window = fromHwnd(hWindow);
glfwSetWindowSize(window, int32_t(Width), int32_t(Height));
WsiLibrary::get()->glfwSetWindowSize(window, int32_t(Width), int32_t(Height));
}
@ -51,7 +51,7 @@ namespace dxvk::wsi {
return false;
int32_t displayCount = 0;
GLFWmonitor** monitors = glfwGetMonitors(&displayCount);
GLFWmonitor** monitors = WsiLibrary::get()->glfwGetMonitors(&displayCount);
GLFWmonitor* monitor = monitors[displayId];
GLFWvidmode wantedMode = {};
@ -62,7 +62,7 @@ namespace dxvk::wsi {
: 0;
// TODO: Implement lookup format for bitsPerPixel here.
glfwSetWindowMonitor(window, monitor, 0, 0, wantedMode.width, wantedMode.width, wantedMode.refreshRate);
WsiLibrary::get()->glfwSetWindowMonitor(window, monitor, 0, 0, wantedMode.width, wantedMode.width, wantedMode.refreshRate);
return true;
}
@ -78,12 +78,12 @@ namespace dxvk::wsi {
if (!isDisplayValid(displayId))
return false;
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
auto videoMode = glfwGetVideoMode(monitor);
GLFWmonitor* monitor = WsiLibrary::get()->glfwGetPrimaryMonitor();
auto videoMode = WsiLibrary::get()->glfwGetVideoMode(monitor);
// TODO: Set this on the correct monitor.
// Docs aren't clear on this...
glfwSetWindowMonitor(window, monitor, 0, 0, videoMode->width, videoMode->height, videoMode->refreshRate);
WsiLibrary::get()->glfwSetWindowMonitor(window, monitor, 0, 0, videoMode->width, videoMode->height, videoMode->refreshRate);
return true;
}
@ -95,9 +95,9 @@ namespace dxvk::wsi {
bool restoreCoordinates) {
GLFWwindow* window = fromHwnd(hWindow);
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
auto videoMode = glfwGetVideoMode(monitor);
glfwSetWindowMonitor(window, nullptr, 0, 0, videoMode->width, videoMode->height, videoMode->refreshRate);
GLFWmonitor* monitor = WsiLibrary::get()->glfwGetPrimaryMonitor();
auto videoMode = WsiLibrary::get()->glfwGetVideoMode(monitor);
WsiLibrary::get()->glfwSetWindowMonitor(window, nullptr, 0, 0, videoMode->width, videoMode->height, videoMode->refreshRate);
return true;
}
@ -138,16 +138,16 @@ namespace dxvk::wsi {
VkSurfaceKHR* pSurface) {
GLFWwindow* window = fromHwnd(hWindow);
return glfwCreateWindowSurface(instance, window, nullptr, pSurface);
return WsiLibrary::get()->glfwCreateWindowSurface(instance, window, nullptr, pSurface);
}
std::vector<const char *> getInstanceExtensions() {
if (!glfwVulkanSupported())
if (!WsiLibrary::get()->glfwVulkanSupported())
throw DxvkError(str::format("GLFW WSI: Vulkan is not supported in any capacity!"));
uint32_t extensionCount = 0;
const char** extensionArray = glfwGetRequiredInstanceExtensions(&extensionCount);
const char** extensionArray = WsiLibrary::get()->glfwGetRequiredInstanceExtensions(&extensionCount);
if (extensionCount == 0)
throw DxvkError(str::format("GLFW WSI: Failed to get required instance extensions"));

View File

@ -15,21 +15,20 @@ wsi_sdl2_src = [
wsi_glfw_src = [
'glfw/wsi_monitor_glfw.cpp',
'glfw/wsi_platform_glfw.cpp',
'glfw/wsi_window_glfw.cpp',
]
if dxvk_wsi == 'win32'
wsi_src = wsi_common_src + wsi_win32_src
wsi_deps = [ dep_displayinfo ]
elif dxvk_wsi == 'sdl2'
wsi_src = wsi_common_src + wsi_sdl2_src
wsi_deps = [ dep_displayinfo ]
elif dxvk_wsi == 'glfw'
wsi_src = wsi_common_src + wsi_glfw_src
wsi_deps = [ dep_displayinfo, lib_glfw ]
else
error('Unknown wsi')
endif
wsi_deps = [ dep_displayinfo ]
wsi_lib = static_library('wsi', wsi_src,
dependencies : wsi_deps,