Skip to content

Commit

Permalink
[wsi] Add GLFW backend
Browse files Browse the repository at this point in the history
  • Loading branch information
Beyley authored and doitsujin committed Jan 8, 2023
1 parent 3491895 commit c11a63f
Show file tree
Hide file tree
Showing 11 changed files with 432 additions and 4 deletions.
25 changes: 25 additions & 0 deletions include/native/wsi/native_glfw.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <windows.h>

#include <GLFW/glfw3.h>

namespace dxvk::wsi {

inline GLFWwindow* fromHwnd(HWND hWindow) {
return reinterpret_cast<GLFWwindow*>(hWindow);
}

inline HWND toHwnd(GLFWwindow* pWindow) {
return reinterpret_cast<HWND>(pWindow);
}

// Offset so null HMONITORs go to -1
inline int32_t fromHmonitor(HMONITOR hMonitor) {
return static_cast<int32_t>(reinterpret_cast<intptr_t>(hMonitor)) - 1;
}

// Offset so -1 display id goes to 0 == NULL
inline HMONITOR toHmonitor(int32_t displayId) {
return reinterpret_cast<HMONITOR>(static_cast<intptr_t>(displayId + 1));
}

}
2 changes: 2 additions & 0 deletions include/native/wsi/native_wsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#error You shouldnt be using this code path.
#elif DXVK_WSI_SDL2
#include "wsi/native_sdl2.h"
#elif DXVK_WSI_GLFW
#include "wsi/native_glfw.h"
#else
#error Unknown wsi!
#endif
14 changes: 10 additions & 4 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,6 @@ if platform == 'windows'
dxvk_name_prefix = ''
compiler_args += ['-DDXVK_WSI_WIN32']
else
lib_sdl2 = cpp.find_library('SDL2')

wrc = find_program('touch')
wrc_generator = generator(wrc, output : [ '@BASENAME@_ignored.h' ], arguments : [ '@OUTPUT@' ] )

Expand All @@ -114,9 +112,17 @@ else
'./include/native/directx'
]

dxvk_wsi = 'sdl2'
dxvk_wsi = get_option('dxvk_native_wsi')

if dxvk_wsi == 'sdl2'
lib_sdl2 = cpp.find_library('SDL2')
compiler_args += ['-DDXVK_WSI_SDL2']
elif dxvk_wsi == 'glfw'
lib_glfw = cpp.find_library('glfw')
compiler_args += ['-DDXVK_WSI_GLFW']
endif

dxvk_name_prefix = 'libdxvk_'
compiler_args += ['-DDXVK_WSI_SDL2']

link_args += [
'-static-libgcc',
Expand Down
2 changes: 2 additions & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ option('enable_d3d9', type : 'boolean', value : true, description: 'Build D3D9'
option('enable_d3d10', type : 'boolean', value : true, description: 'Build D3D10')
option('enable_d3d11', type : 'boolean', value : true, description: 'Build D3D11')
option('build_id', type : 'boolean', value : false)

option('dxvk_native_wsi', type : 'string', value : 'sdl2', description: 'WSI system to use if building natively.')
4 changes: 4 additions & 0 deletions src/dxvk/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ elif dxvk_wsi == 'sdl2'
dxvk_src += [
'platform/dxvk_sdl2_exts.cpp'
]
elif dxvk_wsi == 'glfw'
dxvk_src += [
'platform/dxvk_glfw_exts.cpp'
]
endif

dxvk_extra_deps = [ dependency('threads') ]
Expand Down
49 changes: 49 additions & 0 deletions src/dxvk/platform/dxvk_glfw_exts.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "../dxvk_platform_exts.h"

#include "../../vulkan/vulkan_loader.h"
#include <GLFW/glfw3.h>

namespace dxvk {

DxvkPlatformExts DxvkPlatformExts::s_instance;

std::string_view DxvkPlatformExts::getName() {
return "GLFW WSI";
}

DxvkNameSet DxvkPlatformExts::getInstanceExtensions() {
if (!glfwVulkanSupported())
throw DxvkError(str::format("GLFW WSI: Vulkan is not supported in any capacity!"));

uint32_t extensionCount = 0;
const char** extensionArray = glfwGetRequiredInstanceExtensions(&extensionCount);

if (extensionCount == 0)
throw DxvkError(str::format("GLFW WSI: Failed to get required instance extensions"));

DxvkNameSet names;
for (uint32_t i = 0; i < extensionCount; ++i) {
names.add(extensionArray[i]);
}

return names;
}


DxvkNameSet DxvkPlatformExts::getDeviceExtensions(
uint32_t adapterId) {
return DxvkNameSet();
}


void DxvkPlatformExts::initInstanceExtensions() {
//Nothing needs to be done here on GLFW
}


void DxvkPlatformExts::initDeviceExtensions(
const DxvkInstance* instance) {
//Nothing needs to be done here on GLFW
}

}
163 changes: 163 additions & 0 deletions src/wsi/glfw/wsi_monitor_glfw.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#include "../wsi_monitor.h"

#include "wsi/native_wsi.h"
#include "wsi_platform_glfw.h"

#include "../../util/util_string.h"
#include "../../util/log/log.h"

#include <string>
#include <sstream>

namespace dxvk::wsi {

HMONITOR getDefaultMonitor() {
return enumMonitors(0);
}


HMONITOR enumMonitors(uint32_t index) {
return isDisplayValid(int32_t(index))
? toHmonitor(index)
: nullptr;
}

bool getDisplayName(
HMONITOR hMonitor,
WCHAR (&Name)[32]) {
const int32_t displayId = fromHmonitor(hMonitor);

if (!isDisplayValid(displayId))
return false;

std::wstringstream nameStream;
nameStream << LR"(\\.\DISPLAY)" << (displayId + 1);

std::wstring name = nameStream.str();

std::memset(Name, 0, sizeof(Name));
name.copy(Name, name.length(), 0);

return true;
}


bool getDesktopCoordinates(
HMONITOR hMonitor,
RECT* pRect) {
const int32_t displayId = fromHmonitor(hMonitor);

if (!isDisplayValid(displayId))
return false;

int32_t displayCount = 0;
GLFWmonitor** monitors = glfwGetMonitors(&displayCount);
GLFWmonitor* monitor = monitors[displayId];

int32_t x;
int32_t y;
int32_t w;
int32_t h;
glfwGetMonitorWorkarea(monitor, &x, &y, &w, &h);

pRect->left = x;
pRect->top = y;
pRect->right = x + w;
pRect->bottom = y + h;

return true;
}

static inline uint32_t roundToNextPow2(uint32_t num) {
if (num-- == 0)
return 0;

num |= num >> 1;
num |= num >> 2;
num |= num >> 4;
num |= num >> 8;
num |= num >> 16;

return ++num;
}


static inline void convertMode(const GLFWvidmode& mode, WsiMode* pMode) {
pMode->width = uint32_t(mode.width);
pMode->height = uint32_t(mode.height);
pMode->refreshRate = WsiRational{uint32_t(mode.refreshRate) * 1000, 1000};
// BPP should always be a power of two
// to match Windows behaviour of including padding.
pMode->bitsPerPixel = roundToNextPow2(mode.blueBits + mode.redBits + mode.greenBits);
pMode->interlaced = false;
}


bool getDisplayMode(
HMONITOR hMonitor,
uint32_t ModeNumber,
WsiMode* pMode) {
const int32_t displayId = fromHmonitor(hMonitor);
int32_t displayCount = 0;
GLFWmonitor** monitors = glfwGetMonitors(&displayCount);
GLFWmonitor* monitor = monitors[displayId];

if (!isDisplayValid(displayId))
return false;

int32_t count = 0;
const GLFWvidmode* modes = glfwGetVideoModes(monitor, &count);

if(ModeNumber >= uint32_t(count))
return false;

convertMode(modes[ModeNumber], pMode);

return true;
}


bool getCurrentDisplayMode(
HMONITOR hMonitor,
WsiMode* pMode) {
const int32_t displayId = fromHmonitor(hMonitor);

if (!isDisplayValid(displayId))
return false;

int32_t displayCount = 0;
GLFWmonitor** monitors = glfwGetMonitors(&displayCount);
GLFWmonitor* monitor = monitors[displayId];

const GLFWvidmode* mode = glfwGetVideoMode(monitor);

convertMode(*mode, pMode);

return true;
}


bool getDesktopDisplayMode(
HMONITOR hMonitor,
WsiMode* pMode) {
const int32_t displayId = fromHmonitor(hMonitor);

if (!isDisplayValid(displayId))
return false;

int32_t displayCount = 0;
GLFWmonitor** monitors = glfwGetMonitors(&displayCount);
GLFWmonitor* monitor = monitors[displayId];

//TODO: actually implement this properly, currently we just grab the current one
convertMode(*glfwGetVideoMode(monitor), pMode);

return true;
}

std::vector<uint8_t> getMonitorEdid(HMONITOR hMonitor) {
Logger::err("getMonitorEdid not implemented on this platform.");
return {};
}

}
23 changes: 23 additions & 0 deletions src/wsi/glfw/wsi_platform_glfw.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once

#include "../../vulkan/vulkan_loader.h"
#include <GLFW/glfw3.h>

#include "../wsi_monitor.h"

namespace dxvk::wsi {

/**
* \brief Impl-dependent state
*/
struct DxvkWindowState {
};

inline bool isDisplayValid(int32_t displayId) {
int32_t displayCount = 0;
glfwGetMonitors(&displayCount);

return displayId < displayCount && displayId >= 0;
}

}
Loading

0 comments on commit c11a63f

Please sign in to comment.