summaryrefslogtreecommitdiffstats
path: root/platform/windows/os_windows.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platform/windows/os_windows.cpp')
-rw-r--r--platform/windows/os_windows.cpp126
1 files changed, 83 insertions, 43 deletions
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 157702655e..7316992b60 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -166,15 +166,9 @@ void OS_Windows::initialize_debugging() {
static void _error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, bool p_editor_notify, ErrorHandlerType p_type) {
String err_str;
if (p_errorexp && p_errorexp[0]) {
- err_str = String::utf8(p_errorexp);
+ err_str = String::utf8(p_errorexp) + "\n";
} else {
- err_str = String::utf8(p_file) + ":" + itos(p_line) + " - " + String::utf8(p_error);
- }
-
- if (p_editor_notify) {
- err_str += " (User)\n";
- } else {
- err_str += "\n";
+ err_str = String::utf8(p_file) + ":" + itos(p_line) + " - " + String::utf8(p_error) + "\n";
}
OutputDebugStringW((LPCWSTR)err_str.utf16().ptr());
@@ -379,6 +373,8 @@ Error OS_Windows::open_dynamic_library(const String &p_path, void *&p_library_ha
//this code exists so gdextension can load .dll files from within the executable path
path = get_executable_path().get_base_dir().path_join(p_path.get_file());
}
+ // Path to load from may be different from original if we make copies.
+ String load_path = path;
ERR_FAIL_COND_V(!FileAccess::exists(path), ERR_FILE_NOT_FOUND);
@@ -387,25 +383,22 @@ Error OS_Windows::open_dynamic_library(const String &p_path, void *&p_library_ha
if (p_data != nullptr && p_data->generate_temp_files) {
// Copy the file to the same directory as the original with a prefix in the name.
// This is so relative path to dependencies are satisfied.
- String copy_path = path.get_base_dir().path_join("~" + path.get_file());
+ load_path = path.get_base_dir().path_join("~" + path.get_file());
// If there's a left-over copy (possibly from a crash) then delete it first.
- if (FileAccess::exists(copy_path)) {
- DirAccess::remove_absolute(copy_path);
+ if (FileAccess::exists(load_path)) {
+ DirAccess::remove_absolute(load_path);
}
- Error copy_err = DirAccess::copy_absolute(path, copy_path);
+ Error copy_err = DirAccess::copy_absolute(path, load_path);
if (copy_err) {
ERR_PRINT("Error copying library: " + path);
return ERR_CANT_CREATE;
}
- FileAccess::set_hidden_attribute(copy_path, true);
-
- // Save the copied path so it can be deleted later.
- path = copy_path;
+ FileAccess::set_hidden_attribute(load_path, true);
- Error pdb_err = WindowsUtils::copy_and_rename_pdb(path);
+ Error pdb_err = WindowsUtils::copy_and_rename_pdb(load_path);
if (pdb_err != OK && pdb_err != ERR_SKIP) {
WARN_PRINT(vformat("Failed to rename the PDB file. The original PDB file for '%s' will be loaded.", path));
}
@@ -421,21 +414,21 @@ Error OS_Windows::open_dynamic_library(const String &p_path, void *&p_library_ha
DLL_DIRECTORY_COOKIE cookie = nullptr;
if (p_data != nullptr && p_data->also_set_library_path && has_dll_directory_api) {
- cookie = add_dll_directory((LPCWSTR)(path.get_base_dir().utf16().get_data()));
+ cookie = add_dll_directory((LPCWSTR)(load_path.get_base_dir().utf16().get_data()));
}
- p_library_handle = (void *)LoadLibraryExW((LPCWSTR)(path.utf16().get_data()), nullptr, (p_data != nullptr && p_data->also_set_library_path && has_dll_directory_api) ? LOAD_LIBRARY_SEARCH_DEFAULT_DIRS : 0);
+ p_library_handle = (void *)LoadLibraryExW((LPCWSTR)(load_path.utf16().get_data()), nullptr, (p_data != nullptr && p_data->also_set_library_path && has_dll_directory_api) ? LOAD_LIBRARY_SEARCH_DEFAULT_DIRS : 0);
if (!p_library_handle) {
if (p_data != nullptr && p_data->generate_temp_files) {
- DirAccess::remove_absolute(path);
+ DirAccess::remove_absolute(load_path);
}
#ifdef DEBUG_ENABLED
DWORD err_code = GetLastError();
- HashSet<String> checekd_libs;
+ HashSet<String> checked_libs;
HashSet<String> missing_libs;
- debug_dynamic_library_check_dependencies(path, path, checekd_libs, missing_libs);
+ debug_dynamic_library_check_dependencies(load_path, load_path, checked_libs, missing_libs);
if (!missing_libs.is_empty()) {
String missing;
for (const String &E : missing_libs) {
@@ -464,7 +457,8 @@ Error OS_Windows::open_dynamic_library(const String &p_path, void *&p_library_ha
}
if (p_data != nullptr && p_data->generate_temp_files) {
- temp_libraries[p_library_handle] = path;
+ // Save the copied path so it can be deleted later.
+ temp_libraries[p_library_handle] = load_path;
}
return OK;
@@ -622,6 +616,72 @@ Vector<String> OS_Windows::get_video_adapter_driver_info() const {
return info;
}
+bool OS_Windows::get_user_prefers_integrated_gpu() const {
+ // On Windows 10, the preferred GPU configured in Windows Settings is
+ // stored in the registry under the key
+ // `HKEY_CURRENT_USER\SOFTWARE\Microsoft\DirectX\UserGpuPreferences`
+ // with the name being the app ID or EXE path. The value is in the form of
+ // `GpuPreference=1;`, with the value being 1 for integrated GPU and 2
+ // for discrete GPU. On Windows 11, there may be more flags, separated
+ // by semicolons.
+
+ // If this is a packaged app, use the "application user model ID".
+ // Otherwise, use the EXE path.
+ WCHAR value_name[32768];
+ bool is_packaged = false;
+ {
+ HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
+ if (kernel32) {
+ using GetCurrentApplicationUserModelIdPtr = LONG(WINAPI *)(UINT32 * length, PWSTR id);
+ GetCurrentApplicationUserModelIdPtr GetCurrentApplicationUserModelId = (GetCurrentApplicationUserModelIdPtr)GetProcAddress(kernel32, "GetCurrentApplicationUserModelId");
+
+ if (GetCurrentApplicationUserModelId) {
+ UINT32 length = sizeof(value_name) / sizeof(value_name[0]);
+ LONG result = GetCurrentApplicationUserModelId(&length, value_name);
+ if (result == ERROR_SUCCESS) {
+ is_packaged = true;
+ }
+ }
+ }
+ }
+ if (!is_packaged && GetModuleFileNameW(nullptr, value_name, sizeof(value_name) / sizeof(value_name[0])) >= sizeof(value_name) / sizeof(value_name[0])) {
+ // Paths should never be longer than 32767, but just in case.
+ return false;
+ }
+
+ LPCWSTR subkey = L"SOFTWARE\\Microsoft\\DirectX\\UserGpuPreferences";
+ HKEY hkey = nullptr;
+ LSTATUS result = RegOpenKeyExW(HKEY_CURRENT_USER, subkey, 0, KEY_READ, &hkey);
+ if (result != ERROR_SUCCESS) {
+ return false;
+ }
+
+ DWORD size = 0;
+ result = RegGetValueW(hkey, nullptr, value_name, RRF_RT_REG_SZ, nullptr, nullptr, &size);
+ if (result != ERROR_SUCCESS || size == 0) {
+ RegCloseKey(hkey);
+ return false;
+ }
+
+ Vector<WCHAR> buffer;
+ buffer.resize(size / sizeof(WCHAR));
+ result = RegGetValueW(hkey, nullptr, value_name, RRF_RT_REG_SZ, nullptr, (LPBYTE)buffer.ptrw(), &size);
+ if (result != ERROR_SUCCESS) {
+ RegCloseKey(hkey);
+ return false;
+ }
+
+ RegCloseKey(hkey);
+ const String flags = String::utf16((const char16_t *)buffer.ptr(), size / sizeof(WCHAR));
+
+ for (const String &flag : flags.split(";", false)) {
+ if (flag == "GpuPreference=1") {
+ return true;
+ }
+ }
+ return false;
+}
+
OS::DateTime OS_Windows::get_datetime(bool p_utc) const {
SYSTEMTIME systemtime;
if (p_utc) {
@@ -1634,26 +1694,6 @@ String OS_Windows::get_locale() const {
return "en";
}
-// We need this because GetSystemInfo() is unreliable on WOW64
-// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms724381(v=vs.85).aspx
-// Taken from MSDN
-typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
-LPFN_ISWOW64PROCESS fnIsWow64Process;
-
-BOOL is_wow64() {
- BOOL wow64 = FALSE;
-
- fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
-
- if (fnIsWow64Process) {
- if (!fnIsWow64Process(GetCurrentProcess(), &wow64)) {
- wow64 = FALSE;
- }
- }
-
- return wow64;
-}
-
String OS_Windows::get_processor_name() const {
const String id = "Hardware\\Description\\System\\CentralProcessor\\0";