mirror of
https://github.com/ValveSoftware/Proton.git
synced 2025-06-24 19:39:36 +03:00
steam_helper: Remove now unnecessary OpenVR registry initialization.
CW-Bug-Id: #24510
This commit is contained in:
parent
146b3d0803
commit
244b6a9b15
@ -370,7 +370,6 @@ all-dist: $(DIST_WINEOPENXR64_JSON)
|
||||
|
||||
STEAMEXE_CFLAGS = \
|
||||
-I$(SRC)/lsteamclient/steamworks_sdk_142/ \
|
||||
-I$(SRC)/openvr/headers/ \
|
||||
|
||||
STEAMEXE_LDFLAGS = \
|
||||
-L$(SRC)/steam_helper/32/ \
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include <limits.h>
|
||||
#define _USE_GNU
|
||||
#include <dlfcn.h>
|
||||
#include <string>
|
||||
|
||||
#pragma push_macro("_WIN32")
|
||||
#pragma push_macro("__cdecl")
|
||||
@ -67,15 +68,11 @@
|
||||
#include "wine/unixlib.h"
|
||||
#include "wine/heap.h"
|
||||
#include "wine/vulkan.h"
|
||||
#include "openvr.h"
|
||||
#include "../src/ivrclientcore.h"
|
||||
|
||||
#include <msi.h>
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(steam);
|
||||
|
||||
static const WCHAR PROTON_VR_RUNTIME_W[] = {'P','R','O','T','O','N','_','V','R','_','R','U','N','T','I','M','E',0};
|
||||
|
||||
static bool env_nonzero(const char *env)
|
||||
{
|
||||
const char *v = getenv(env);
|
||||
@ -310,376 +307,6 @@ static bool convert_path_to_win(std::string &s)
|
||||
return true;
|
||||
}
|
||||
|
||||
static BOOL set_vr_status(HKEY key, DWORD value)
|
||||
{
|
||||
LSTATUS status;
|
||||
|
||||
if ((status = RegSetValueExA(key, "state", 0, REG_DWORD, (BYTE *)&value, sizeof(value))))
|
||||
{
|
||||
WINE_ERR("Could not set state value, status %#x.\n", status);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void* load_vrclient(void)
|
||||
{
|
||||
WCHAR pathW[PATH_MAX];
|
||||
char *pathU;
|
||||
DWORD sz;
|
||||
|
||||
#ifdef _WIN64
|
||||
static const char append_path[] = "/bin/linux64/vrclient.so";
|
||||
#else
|
||||
static const char append_path[] = "/bin/vrclient.so";
|
||||
#endif
|
||||
|
||||
/* PROTON_VR_RUNTIME is provided by the proton setup script */
|
||||
if(!GetEnvironmentVariableW(PROTON_VR_RUNTIME_W, pathW, ARRAY_SIZE(pathW)))
|
||||
{
|
||||
WINE_TRACE("Linux OpenVR runtime is not available\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sz = WideCharToMultiByte(CP_UNIXCP, 0, pathW, -1, NULL, 0, NULL, NULL);
|
||||
if(!sz)
|
||||
{
|
||||
WINE_ERR("Can't convert path to unixcp! %s\n", wine_dbgstr_w(pathW));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pathU = (char *)HeapAlloc(GetProcessHeap(), 0, sz + sizeof(append_path));
|
||||
|
||||
sz = WideCharToMultiByte(CP_UNIXCP, 0, pathW, -1, pathU, sz, NULL, NULL);
|
||||
if(!sz)
|
||||
{
|
||||
WINE_ERR("Can't convert path to unixcp! %s\n", wine_dbgstr_w(pathW));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcat(pathU, append_path);
|
||||
|
||||
WINE_TRACE("got openvr runtime path: %s\n", pathU);
|
||||
|
||||
return dlopen(pathU, RTLD_NOW);
|
||||
}
|
||||
|
||||
static char *strdupA(const char *s)
|
||||
{
|
||||
size_t l = strlen(s) + 1;
|
||||
char *r = (char *)heap_alloc(l);
|
||||
memcpy(r, s, l);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void parse_extensions(const char *in, uint32_t *out_count,
|
||||
char ***out_strs)
|
||||
{
|
||||
char *iter, *start;
|
||||
char **list, *str = strdupA(in);
|
||||
uint32_t extension_count = 0, o = 0;
|
||||
|
||||
iter = str;
|
||||
while(*iter){
|
||||
if(*iter++ == ' ')
|
||||
extension_count++;
|
||||
}
|
||||
/* count the one ending in NUL */
|
||||
if(iter != str)
|
||||
extension_count++;
|
||||
if(!extension_count){
|
||||
*out_count = 0;
|
||||
*out_strs = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
list = (char **)heap_alloc(extension_count * sizeof(*list));
|
||||
|
||||
start = iter = str;
|
||||
do{
|
||||
if(*iter == ' '){
|
||||
*iter = 0;
|
||||
list[o++] = start;
|
||||
WINE_TRACE("added %s to list\n", list[o-1]);
|
||||
iter++;
|
||||
start = iter;
|
||||
}else if(*iter == 0){
|
||||
list[o++] = start;
|
||||
WINE_TRACE("added %s to list\n", list[o-1]);
|
||||
break;
|
||||
}else{
|
||||
iter++;
|
||||
}
|
||||
}while(1);
|
||||
|
||||
*out_count = extension_count;
|
||||
*out_strs = list;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
VkPhysicalDevice __wine_get_native_VkPhysicalDevice(VkPhysicalDevice phys_dev);
|
||||
};
|
||||
|
||||
static void *get_winevulkan_unix_lib_handle(HMODULE hvulkan)
|
||||
{
|
||||
unixlib_handle_t unix_funcs;
|
||||
NTSTATUS status;
|
||||
Dl_info info;
|
||||
|
||||
status = NtQueryVirtualMemory(GetCurrentProcess(), hvulkan, (MEMORY_INFORMATION_CLASS)1000 /*MemoryWineUnixFuncs*/,
|
||||
&unix_funcs, sizeof(unix_funcs), NULL);
|
||||
if (status)
|
||||
{
|
||||
WINE_ERR("NtQueryVirtualMemory status %#x.\n", (int)status);
|
||||
return NULL;
|
||||
}
|
||||
if (!dladdr((void *)(ULONG_PTR)unix_funcs, &info))
|
||||
{
|
||||
WINE_ERR("dladdr failed.\n");
|
||||
return NULL;
|
||||
}
|
||||
WINE_TRACE("path %s.\n", info.dli_fname);
|
||||
return dlopen(info.dli_fname, RTLD_NOW);
|
||||
}
|
||||
|
||||
static DWORD WINAPI initialize_vr_data(void *arg)
|
||||
{
|
||||
vr::IVRClientCore* (*vrclient_VRClientCoreFactory)(const char *name, int *return_code);
|
||||
uint32_t instance_extensions_count, device_count;
|
||||
VkPhysicalDevice *phys_devices = NULL;
|
||||
VkPhysicalDeviceProperties prop = {};
|
||||
VkInstanceCreateInfo inst_info = {};
|
||||
char **instance_extensions = NULL;
|
||||
VkApplicationInfo app_info = {};
|
||||
char *buffer = NULL, *new_buffer;
|
||||
vr::IVRClientCore* client_core;
|
||||
vr::IVRCompositor* compositor;
|
||||
VkInstance vk_instance = NULL;
|
||||
BOOL vr_initialized = FALSE;
|
||||
vr::EVRInitError error;
|
||||
HMODULE hvulkan = NULL;
|
||||
DWORD vr_status = ~0u;
|
||||
unsigned int length;
|
||||
HMODULE hwineopenxr;
|
||||
void *lib_vrclient;
|
||||
void *unix_handle;
|
||||
DWORD hmd_present;
|
||||
int return_code;
|
||||
LSTATUS status;
|
||||
unsigned int i;
|
||||
VkResult res;
|
||||
HKEY vr_key;
|
||||
|
||||
WINE_TRACE("Starting VR info initialization.\n");
|
||||
|
||||
if ((status = RegOpenKeyExA( HKEY_CURRENT_USER, "Software\\Wine\\VR", 0, KEY_ALL_ACCESS, &vr_key )))
|
||||
{
|
||||
WINE_WARN( "Could not create key, status %#x.\n", status );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(lib_vrclient = load_vrclient()))
|
||||
{
|
||||
WINE_ERR("Could not load libopenvr_api.so.\n");
|
||||
set_vr_status(vr_key, ~0u);
|
||||
RegCloseKey(vr_key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(vrclient_VRClientCoreFactory = reinterpret_cast<decltype(vrclient_VRClientCoreFactory)>
|
||||
(dlsym(lib_vrclient, "VRClientCoreFactory"))))
|
||||
{
|
||||
WINE_ERR("Could not find function VRClientCoreFactory.\n");
|
||||
goto done;
|
||||
}
|
||||
if (!(client_core = vrclient_VRClientCoreFactory(vr::IVRClientCore_Version, &return_code)))
|
||||
{
|
||||
WINE_ERR("Could not get IVRClientCore, error %d.\n", return_code);
|
||||
}
|
||||
|
||||
/* Without overriding the app_key vrclient waits 2 seconds for a valid appkey before returning. */
|
||||
error = client_core->Init(vr::VRApplication_Background, NULL);
|
||||
if (error != vr::VRInitError_None)
|
||||
{
|
||||
if (error == vr::VRInitError_Init_NoServerForBackgroundApp)
|
||||
WINE_TRACE("VR server is not available.\n");
|
||||
else
|
||||
WINE_ERR("VR init failed, error %u.\n", error);
|
||||
goto done;
|
||||
}
|
||||
vr_initialized = TRUE;
|
||||
|
||||
hmd_present = !!client_core->BIsHmdPresent();
|
||||
WINE_TRACE("hmd_present %#x.\n", hmd_present);
|
||||
if ((status = RegSetValueExA(vr_key, "is_hmd_present", 0, REG_DWORD, (BYTE *)&hmd_present, sizeof(hmd_present))))
|
||||
WINE_ERR("Could not set is_hmd_present value, status %#x.\n", status);
|
||||
|
||||
compositor = reinterpret_cast<vr::IVRCompositor*>(client_core->GetGenericInterface(vr::IVRCompositor_Version, &error));
|
||||
if (!compositor)
|
||||
{
|
||||
WINE_ERR("Could not get compositor, error %u.\n", error);
|
||||
goto done;
|
||||
}
|
||||
|
||||
length = compositor->GetVulkanInstanceExtensionsRequired(nullptr, 0);
|
||||
if (!(buffer = (char *)heap_alloc(length)))
|
||||
{
|
||||
WINE_ERR("No memory.\n");
|
||||
goto done;
|
||||
}
|
||||
*buffer = 0;
|
||||
compositor->GetVulkanInstanceExtensionsRequired(buffer, length);
|
||||
WINE_TRACE("Instance extensions %s.\n", buffer);
|
||||
|
||||
if ((status = RegSetValueExA(vr_key, "openvr_vulkan_instance_extensions", 0, REG_SZ, (BYTE *)buffer, length)))
|
||||
{
|
||||
WINE_ERR("Could not set openvr_vulkan_instance_extensions value, status %#x.\n", status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!(hvulkan = LoadLibraryA("winevulkan.dll")))
|
||||
{
|
||||
WINE_ERR("Could not load winevulkan.\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
#define USE_VULKAN_PROC(name) decltype(name) *p##name;\
|
||||
if (!(p##name = reinterpret_cast<decltype(name) *>(GetProcAddress(hvulkan, "wine_"#name)))\
|
||||
&& !(p##name = reinterpret_cast<decltype(name) *>(GetProcAddress(hvulkan, #name))))\
|
||||
{\
|
||||
WINE_ERR("Could not find function %s.\n", #name);\
|
||||
goto done;\
|
||||
}
|
||||
USE_VULKAN_PROC(vkCreateInstance)
|
||||
USE_VULKAN_PROC(vkDestroyInstance)
|
||||
USE_VULKAN_PROC(vkEnumeratePhysicalDevices)
|
||||
USE_VULKAN_PROC(vkGetPhysicalDeviceProperties)
|
||||
#undef USE_VULKAN_PROC
|
||||
|
||||
if (!(unix_handle = get_winevulkan_unix_lib_handle(hvulkan)))
|
||||
{
|
||||
WINE_ERR("winevulkan.so not found.\n");
|
||||
goto done;
|
||||
}
|
||||
decltype(__wine_get_native_VkPhysicalDevice) *p__wine_get_native_VkPhysicalDevice;
|
||||
p__wine_get_native_VkPhysicalDevice = reinterpret_cast<decltype(__wine_get_native_VkPhysicalDevice) *>
|
||||
(dlsym(unix_handle, "__wine_get_native_VkPhysicalDevice"));
|
||||
|
||||
dlclose(unix_handle);
|
||||
if (!p__wine_get_native_VkPhysicalDevice)
|
||||
{
|
||||
WINE_ERR("__wine_get_native_VkPhysicalDevice not found.\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
parse_extensions(buffer, &instance_extensions_count, &instance_extensions);
|
||||
|
||||
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
app_info.pApplicationName = "proton_vrhelper";
|
||||
app_info.applicationVersion = 1;
|
||||
app_info.pEngineName = "proton_vrhelper";
|
||||
app_info.engineVersion = 1;
|
||||
app_info.apiVersion = VK_MAKE_VERSION(1, 1, 0);
|
||||
|
||||
inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
inst_info.pApplicationInfo = &app_info;
|
||||
inst_info.enabledExtensionCount = instance_extensions_count;
|
||||
inst_info.ppEnabledExtensionNames = instance_extensions;
|
||||
|
||||
if ((res = pvkCreateInstance(&inst_info, NULL, &vk_instance)) != VK_SUCCESS)
|
||||
{
|
||||
WINE_ERR("Could not create VK instance, res %d.\n", res);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((res = pvkEnumeratePhysicalDevices(vk_instance, &device_count, NULL)) != VK_SUCCESS)
|
||||
{
|
||||
WINE_ERR("Could not enumerate physical devices, res %d.\n", res);
|
||||
goto done;
|
||||
}
|
||||
if (!(phys_devices = (VkPhysicalDevice *)heap_alloc(device_count * sizeof(*phys_devices))))
|
||||
{
|
||||
WINE_ERR("No memory.\n");
|
||||
goto done;
|
||||
}
|
||||
if ((res = pvkEnumeratePhysicalDevices(vk_instance, &device_count, phys_devices)) != VK_SUCCESS)
|
||||
{
|
||||
WINE_ERR("Could not enumerate physical devices, res %d.\n", res);
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (i = 0; i < device_count; ++i)
|
||||
{
|
||||
char name[256];
|
||||
|
||||
pvkGetPhysicalDeviceProperties(phys_devices[i], &prop);
|
||||
if (prop.apiVersion < VK_MAKE_VERSION(1, 1, 0))
|
||||
{
|
||||
WINE_TRACE("Skipping Vulkan 1.0 adapter %s.\n", prop.deviceName);
|
||||
continue;
|
||||
}
|
||||
|
||||
length = compositor->GetVulkanDeviceExtensionsRequired(p__wine_get_native_VkPhysicalDevice(phys_devices[i]), nullptr, 0);
|
||||
if (!(new_buffer = (char *)heap_realloc(buffer, length)))
|
||||
{
|
||||
WINE_ERR("No memory.\n");
|
||||
goto done;
|
||||
}
|
||||
buffer = new_buffer;
|
||||
compositor->GetVulkanDeviceExtensionsRequired(p__wine_get_native_VkPhysicalDevice(phys_devices[i]), buffer, length);
|
||||
sprintf(name, "PCIID:%04x:%04x", prop.vendorID, prop.deviceID);
|
||||
WINE_TRACE("%s: %s.\n", name, buffer);
|
||||
|
||||
if ((status = RegSetValueExA(vr_key, name, 0, REG_SZ, (BYTE *)buffer, length)))
|
||||
{
|
||||
WINE_ERR("Could not set %s value, status %#x.\n", name, status);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (vr_initialized) {
|
||||
client_core->Cleanup();
|
||||
vr_initialized = FALSE;
|
||||
}
|
||||
|
||||
if (!(hwineopenxr = LoadLibraryA("wineopenxr.dll"))) WARN("Could not load wineopenxr.dll, err %u.\n", GetLastError());
|
||||
else
|
||||
{
|
||||
BOOL (CDECL *init)(void);
|
||||
|
||||
if ((init = (decltype(init))GetProcAddress(hwineopenxr, "wineopenxr_init_registry"))) init();
|
||||
else ERR("Failed to find wineopenxr_init_registry export\n");
|
||||
|
||||
FreeLibrary(hwineopenxr);
|
||||
}
|
||||
|
||||
vr_status = 1;
|
||||
|
||||
done:
|
||||
set_vr_status(vr_key, vr_status);
|
||||
|
||||
heap_free(phys_devices);
|
||||
|
||||
if (vk_instance)
|
||||
pvkDestroyInstance(vk_instance, NULL);
|
||||
|
||||
if (instance_extensions)
|
||||
{
|
||||
heap_free(instance_extensions[0]);
|
||||
heap_free(instance_extensions);
|
||||
}
|
||||
if (hvulkan)
|
||||
FreeLibrary(hvulkan);
|
||||
heap_free(buffer);
|
||||
if (vr_initialized)
|
||||
client_core->Cleanup();
|
||||
WINE_TRACE("Completed VR info initialization.\n");
|
||||
dlclose(lib_vrclient);
|
||||
RegCloseKey(vr_key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setup_vr_registry(void)
|
||||
{
|
||||
BOOL (CDECL *init)(void);
|
||||
@ -699,14 +326,8 @@ static void setup_vr_registry(void)
|
||||
if ((init = (decltype(init))GetProcAddress( vrclient, "vrclient_init_registry" ))) init();
|
||||
else ERR( "Failed to find vrclient_init_registry export\n" );
|
||||
|
||||
if (!(thread = CreateThread( NULL, 0, initialize_vr_data, NULL, 0, NULL )))
|
||||
{
|
||||
ERR( "Could not create thread, error %u.\n", GetLastError() );
|
||||
return;
|
||||
}
|
||||
CloseHandle(thread);
|
||||
|
||||
WINE_TRACE("Queued VR info initialization.\n");
|
||||
TRACE( "Queued VR info initialization.\n" );
|
||||
FreeLibrary(vrclient);
|
||||
}
|
||||
|
||||
static WCHAR *strchrW(WCHAR *h, WCHAR n)
|
||||
|
Loading…
x
Reference in New Issue
Block a user