summaryrefslogtreecommitdiff
path: root/platform/windows
diff options
context:
space:
mode:
Diffstat (limited to 'platform/windows')
-rw-r--r--platform/windows/SCsub3
-rw-r--r--platform/windows/context_gl_win.cpp16
-rw-r--r--platform/windows/crash_handler_win.cpp211
-rw-r--r--platform/windows/crash_handler_win.h56
-rw-r--r--platform/windows/detect.py2
-rw-r--r--platform/windows/godot_win.cpp34
-rw-r--r--platform/windows/joypad.cpp4
-rw-r--r--platform/windows/os_windows.cpp41
-rw-r--r--platform/windows/os_windows.h6
9 files changed, 350 insertions, 23 deletions
diff --git a/platform/windows/SCsub b/platform/windows/SCsub
index befbe00183..b56a5c6a80 100644
--- a/platform/windows/SCsub
+++ b/platform/windows/SCsub
@@ -5,6 +5,7 @@ Import('env')
common_win = [
"context_gl_win.cpp",
+ "crash_handler_win.cpp",
"os_windows.cpp",
"ctxgl_procaddr.cpp",
"key_mapping_win.cpp",
@@ -12,7 +13,7 @@ common_win = [
"packet_peer_udp_winsock.cpp",
"stream_peer_winsock.cpp",
"joypad.cpp",
- "power_windows.cpp",
+ "power_windows.cpp",
]
restarget = "godot_res" + env["OBJSUFFIX"]
diff --git a/platform/windows/context_gl_win.cpp b/platform/windows/context_gl_win.cpp
index 328b987f1f..8640f27699 100644
--- a/platform/windows/context_gl_win.cpp
+++ b/platform/windows/context_gl_win.cpp
@@ -130,24 +130,28 @@ Error ContextGL_Win::initialize() {
0, 0, 0 // Layer Masks Ignored
};
- if (!(hDC = GetDC(hWnd))) {
+ hDC = GetDC(hWnd);
+ if (!hDC) {
MessageBox(NULL, "Can't Create A GL Device Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return ERR_CANT_CREATE; // Return FALSE
}
- if (!(pixel_format = ChoosePixelFormat(hDC, &pfd))) // Did Windows Find A Matching Pixel Format?
+ pixel_format = ChoosePixelFormat(hDC, &pfd);
+ if (!pixel_format) // Did Windows Find A Matching Pixel Format?
{
MessageBox(NULL, "Can't Find A Suitable pixel_format.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return ERR_CANT_CREATE; // Return FALSE
}
- if (!SetPixelFormat(hDC, pixel_format, &pfd)) // Are We Able To Set The Pixel Format?
+ BOOL ret = SetPixelFormat(hDC, pixel_format, &pfd);
+ if (!ret) // Are We Able To Set The Pixel Format?
{
MessageBox(NULL, "Can't Set The pixel_format.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return ERR_CANT_CREATE; // Return FALSE
}
- if (!(hRC = wglCreateContext(hDC))) // Are We Able To Get A Rendering Context?
+ hRC = wglCreateContext(hDC);
+ if (!hRC) // Are We Able To Get A Rendering Context?
{
MessageBox(NULL, "Can't Create A Temporary GL Rendering Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return ERR_CANT_CREATE; // Return FALSE
@@ -175,8 +179,8 @@ Error ContextGL_Win::initialize() {
return ERR_CANT_CREATE;
}
- HGLRC new_hRC;
- if (!(new_hRC = wglCreateContextAttribsARB(hDC, 0, attribs))) {
+ HGLRC new_hRC = wglCreateContextAttribsARB(hDC, 0, attribs);
+ if (!new_hRC) {
wglDeleteContext(hRC);
MessageBox(NULL, "Can't Create An OpenGL 3.3 Rendering Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return ERR_CANT_CREATE; // Return false
diff --git a/platform/windows/crash_handler_win.cpp b/platform/windows/crash_handler_win.cpp
new file mode 100644
index 0000000000..c9385f36d6
--- /dev/null
+++ b/platform/windows/crash_handler_win.cpp
@@ -0,0 +1,211 @@
+/*************************************************************************/
+/* crash_handler_win.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "main/main.h"
+#include "os_windows.h"
+
+#ifdef CRASH_HANDLER_EXCEPTION
+
+// Backtrace code code based on: https://stackoverflow.com/questions/6205981/windows-c-stack-trace-from-a-running-app
+
+#include <psapi.h>
+#include <algorithm>
+#include <iterator>
+
+#pragma comment(lib, "psapi.lib")
+#pragma comment(lib, "dbghelp.lib")
+
+// Some versions of imagehlp.dll lack the proper packing directives themselves
+// so we need to do it.
+#pragma pack(push, before_imagehlp, 8)
+#include <imagehlp.h>
+#pragma pack(pop, before_imagehlp)
+
+struct module_data {
+ std::string image_name;
+ std::string module_name;
+ void *base_address;
+ DWORD load_size;
+};
+
+class symbol {
+ typedef IMAGEHLP_SYMBOL64 sym_type;
+ sym_type *sym;
+ static const int max_name_len = 1024;
+
+public:
+ symbol(HANDLE process, DWORD64 address)
+ : sym((sym_type *)::operator new(sizeof(*sym) + max_name_len)) {
+ memset(sym, '\0', sizeof(*sym) + max_name_len);
+ sym->SizeOfStruct = sizeof(*sym);
+ sym->MaxNameLength = max_name_len;
+ DWORD64 displacement;
+
+ SymGetSymFromAddr64(process, address, &displacement, sym);
+ }
+
+ std::string name() { return std::string(sym->Name); }
+ std::string undecorated_name() {
+ if (*sym->Name == '\0')
+ return "<couldn't map PC to fn name>";
+ std::vector<char> und_name(max_name_len);
+ UnDecorateSymbolName(sym->Name, &und_name[0], max_name_len, UNDNAME_COMPLETE);
+ return std::string(&und_name[0], strlen(&und_name[0]));
+ }
+};
+
+class get_mod_info {
+ HANDLE process;
+
+public:
+ get_mod_info(HANDLE h)
+ : process(h) {}
+
+ module_data operator()(HMODULE module) {
+ module_data ret;
+ char temp[4096];
+ MODULEINFO mi;
+
+ GetModuleInformation(process, module, &mi, sizeof(mi));
+ ret.base_address = mi.lpBaseOfDll;
+ ret.load_size = mi.SizeOfImage;
+
+ GetModuleFileNameEx(process, module, temp, sizeof(temp));
+ ret.image_name = temp;
+ GetModuleBaseName(process, module, temp, sizeof(temp));
+ ret.module_name = temp;
+ std::vector<char> img(ret.image_name.begin(), ret.image_name.end());
+ std::vector<char> mod(ret.module_name.begin(), ret.module_name.end());
+ SymLoadModule64(process, 0, &img[0], &mod[0], (DWORD64)ret.base_address, ret.load_size);
+ return ret;
+ }
+};
+
+DWORD CrashHandlerException(EXCEPTION_POINTERS *ep) {
+ HANDLE process = GetCurrentProcess();
+ HANDLE hThread = GetCurrentThread();
+ DWORD offset_from_symbol = 0;
+ IMAGEHLP_LINE64 line = { 0 };
+ std::vector<module_data> modules;
+ DWORD cbNeeded;
+ std::vector<HMODULE> module_handles(1);
+
+ if (OS::get_singleton() == NULL || OS::get_singleton()->is_disable_crash_handler()) {
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ fprintf(stderr, "%s: Program crashed\n", __FUNCTION__);
+
+ // Load the symbols:
+ if (!SymInitialize(process, NULL, false))
+ return EXCEPTION_CONTINUE_SEARCH;
+
+ SymSetOptions(SymGetOptions() | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
+ EnumProcessModules(process, &module_handles[0], module_handles.size() * sizeof(HMODULE), &cbNeeded);
+ module_handles.resize(cbNeeded / sizeof(HMODULE));
+ EnumProcessModules(process, &module_handles[0], module_handles.size() * sizeof(HMODULE), &cbNeeded);
+ std::transform(module_handles.begin(), module_handles.end(), std::back_inserter(modules), get_mod_info(process));
+ void *base = modules[0].base_address;
+
+ // Setup stuff:
+ CONTEXT *context = ep->ContextRecord;
+ STACKFRAME64 frame;
+ bool skip_first = false;
+
+ frame.AddrPC.Mode = AddrModeFlat;
+ frame.AddrStack.Mode = AddrModeFlat;
+ frame.AddrFrame.Mode = AddrModeFlat;
+
+#ifdef _M_X64
+ frame.AddrPC.Offset = context->Rip;
+ frame.AddrStack.Offset = context->Rsp;
+ frame.AddrFrame.Offset = context->Rbp;
+#else
+ frame.AddrPC.Offset = context->Eip;
+ frame.AddrStack.Offset = context->Esp;
+ frame.AddrFrame.Offset = context->Ebp;
+
+ // Skip the first one to avoid a duplicate on 32-bit mode
+ skip_first = true;
+#endif
+
+ line.SizeOfStruct = sizeof(line);
+ IMAGE_NT_HEADERS *h = ImageNtHeader(base);
+ DWORD image_type = h->FileHeader.Machine;
+ int n = 0;
+ String msg = GLOBAL_GET("debug/settings/backtrace/message");
+
+ fprintf(stderr, "Dumping the backtrace. %ls\n", msg.c_str());
+
+ do {
+ if (skip_first) {
+ skip_first = false;
+ } else {
+ if (frame.AddrPC.Offset != 0) {
+ std::string fnName = symbol(process, frame.AddrPC.Offset).undecorated_name();
+
+ if (SymGetLineFromAddr64(process, frame.AddrPC.Offset, &offset_from_symbol, &line))
+ fprintf(stderr, "[%d] %s (%s:%d)\n", n, fnName.c_str(), line.FileName, line.LineNumber);
+ else
+ fprintf(stderr, "[%d] %s\n", n, fnName.c_str());
+ } else
+ fprintf(stderr, "[%d] ???\n", n);
+
+ n++;
+ }
+
+ if (!StackWalk64(image_type, process, hThread, &frame, context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
+ break;
+ } while (frame.AddrReturn.Offset != 0 && n < 256);
+
+ fprintf(stderr, "-- END OF BACKTRACE --\n");
+
+ SymCleanup(process);
+
+ // Pass the exception to the OS
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+#endif
+
+CrashHandler::CrashHandler() {
+ disabled = false;
+}
+
+CrashHandler::~CrashHandler() {
+}
+
+void CrashHandler::disable() {
+ if (disabled)
+ return;
+
+ disabled = true;
+}
+
+void CrashHandler::initialize() {
+}
diff --git a/platform/windows/crash_handler_win.h b/platform/windows/crash_handler_win.h
new file mode 100644
index 0000000000..0b1889e4fe
--- /dev/null
+++ b/platform/windows/crash_handler_win.h
@@ -0,0 +1,56 @@
+/*************************************************************************/
+/* crash_handler_win.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef CRASH_HANDLER_WIN_H
+#define CRASH_HANDLER_WIN_H
+
+#include <windows.h>
+
+// Crash handler exception only enabled with MSVC
+#if defined(DEBUG_ENABLED) && defined(MSVC)
+#define CRASH_HANDLER_EXCEPTION 1
+
+extern DWORD CrashHandlerException(EXCEPTION_POINTERS *ep);
+#endif
+
+class CrashHandler {
+
+ bool disabled;
+
+public:
+ void initialize();
+
+ void disable();
+ bool is_disabled() const { return disabled; };
+
+ CrashHandler();
+ ~CrashHandler();
+};
+
+#endif
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index d239ccf7d2..a7cca23973 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -123,7 +123,7 @@ def configure(env):
env.Append(LINKFLAGS=['/ENTRY:mainCRTStartup'])
elif (env["target"] == "debug"):
- env.Append(CCFLAGS=['/Z7', '/DDEBUG_ENABLED', '/DDEBUG_MEMORY_ENABLED', '/DD3D_DEBUG_INFO', '/Od'])
+ env.Append(CCFLAGS=['/Z7', '/DDEBUG_ENABLED', '/DDEBUG_MEMORY_ENABLED', '/DD3D_DEBUG_INFO', '/Od', '/EHsc'])
env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
env.Append(LINKFLAGS=['/DEBUG'])
diff --git a/platform/windows/godot_win.cpp b/platform/windows/godot_win.cpp
index d2ac6ecb50..4450cb3670 100644
--- a/platform/windows/godot_win.cpp
+++ b/platform/windows/godot_win.cpp
@@ -157,24 +157,32 @@ int widechar_main(int argc, wchar_t **argv) {
};
int main(int _argc, char **_argv) {
- // _argc and _argv are ignored
- // we are going to use the WideChar version of them instead
+// _argc and _argv are ignored
+// we are going to use the WideChar version of them instead
- LPWSTR *wc_argv;
- int argc;
- int result;
+#ifdef CRASH_HANDLER_EXCEPTION
+ __try {
+#endif
+ LPWSTR *wc_argv;
+ int argc;
+ int result;
- wc_argv = CommandLineToArgvW(GetCommandLineW(), &argc);
+ wc_argv = CommandLineToArgvW(GetCommandLineW(), &argc);
- if (NULL == wc_argv) {
- wprintf(L"CommandLineToArgvW failed\n");
- return 0;
- }
+ if (NULL == wc_argv) {
+ wprintf(L"CommandLineToArgvW failed\n");
+ return 0;
+ }
- result = widechar_main(argc, wc_argv);
+ result = widechar_main(argc, wc_argv);
- LocalFree(wc_argv);
- return result;
+ LocalFree(wc_argv);
+ return result;
+#ifdef CRASH_HANDLER_EXCEPTION
+ } __except (CrashHandlerException(GetExceptionInformation())) {
+ return 1;
+ }
+#endif
}
HINSTANCE godot_hinstance = NULL;
diff --git a/platform/windows/joypad.cpp b/platform/windows/joypad.cpp
index 00cfa812de..0c7358f499 100644
--- a/platform/windows/joypad.cpp
+++ b/platform/windows/joypad.cpp
@@ -379,7 +379,9 @@ void JoypadWindows::process_joypads() {
IDirectInputDevice8_Acquire(joy->di_joy);
joy->di_joy->Poll();
}
- if (FAILED(hr = joy->di_joy->GetDeviceState(sizeof(DIJOYSTATE2), &js))) {
+
+ hr = joy->di_joy->GetDeviceState(sizeof(DIJOYSTATE2), &js);
+ if (FAILED(hr)) {
//printf("failed to read joy #%d\n", i);
continue;
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index deb9c25576..530072db6e 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -164,6 +164,8 @@ const char *OS_Windows::get_audio_driver_name(int p_driver) const {
void OS_Windows::initialize_core() {
+ crash_handler.initialize();
+
last_button_state = 0;
//RedirectIOToConsole();
@@ -887,6 +889,12 @@ static int QueryDpiForMonitor(HMONITOR hmon, _MonitorDpiType dpiType = MDT_Defau
return (dpiX + dpiY) / 2;
}
+typedef enum _SHC_PROCESS_DPI_AWARENESS {
+ SHC_PROCESS_DPI_UNAWARE = 0,
+ SHC_PROCESS_SYSTEM_DPI_AWARE = 1,
+ SHC_PROCESS_PER_MONITOR_DPI_AWARE = 2
+} SHC_PROCESS_DPI_AWARENESS;
+
void OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
main_loop = NULL;
@@ -894,6 +902,20 @@ void OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
window_has_focus = true;
WNDCLASSEXW wc;
+ if (is_hidpi_allowed()) {
+ HMODULE Shcore = LoadLibraryW(L"Shcore.dll");
+
+ if (Shcore != NULL) {
+ typedef HRESULT(WINAPI * SetProcessDpiAwareness_t)(SHC_PROCESS_DPI_AWARENESS);
+
+ SetProcessDpiAwareness_t SetProcessDpiAwareness = (SetProcessDpiAwareness_t)GetProcAddress(Shcore, "SetProcessDpiAwareness");
+
+ if (SetProcessDpiAwareness) {
+ SetProcessDpiAwareness(SHC_PROCESS_SYSTEM_DPI_AWARE);
+ }
+ }
+ }
+
video_mode = p_desired;
//printf("**************** desired %s, mode %s\n", p_desired.fullscreen?"true":"false", video_mode.fullscreen?"true":"false");
RECT WindowRect;
@@ -996,7 +1018,16 @@ void OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
video_mode.fullscreen = false;
} else {
- if (!(hWnd = CreateWindowExW(dwExStyle, L"Engine", L"", dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, (GetSystemMetrics(SM_CXSCREEN) - WindowRect.right) / 2, (GetSystemMetrics(SM_CYSCREEN) - WindowRect.bottom) / 2, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, NULL, NULL, hInstance, NULL))) {
+ hWnd = CreateWindowExW(
+ dwExStyle,
+ L"Engine", L"",
+ dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
+ (GetSystemMetrics(SM_CXSCREEN) - WindowRect.right) / 2,
+ (GetSystemMetrics(SM_CYSCREEN) - WindowRect.bottom) / 2,
+ WindowRect.right - WindowRect.left,
+ WindowRect.bottom - WindowRect.top,
+ NULL, NULL, hInstance, NULL);
+ if (!hWnd) {
MessageBoxW(NULL, L"Window Creation Error.", L"ERROR", MB_OK | MB_ICONEXCLAMATION);
return; // Return FALSE
}
@@ -2339,6 +2370,14 @@ bool OS_Windows::_check_internal_feature_support(const String &p_feature) {
return p_feature == "pc" || p_feature == "s3tc";
}
+void OS_Windows::disable_crash_handler() {
+ crash_handler.disable();
+}
+
+bool OS_Windows::is_disable_crash_handler() const {
+ return crash_handler.is_disabled();
+}
+
OS_Windows::OS_Windows(HINSTANCE _hInstance) {
key_event_pos = 0;
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 0c5965bf51..474b0fea5c 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -31,6 +31,7 @@
#define OS_WINDOWS_H
#include "context_gl_win.h"
+#include "crash_handler_win.h"
#include "drivers/rtaudio/audio_driver_rtaudio.h"
#include "drivers/wasapi/audio_driver_wasapi.h"
#include "os/input.h"
@@ -134,6 +135,8 @@ class OS_Windows : public OS {
AudioDriverXAudio2 driver_xaudio2;
#endif
+ CrashHandler crash_handler;
+
void _drag_event(int p_x, int p_y, int idx);
void _touch_event(bool p_pressed, int p_x, int p_y, int idx);
@@ -284,6 +287,9 @@ public:
virtual bool _check_internal_feature_support(const String &p_feature);
+ void disable_crash_handler();
+ bool is_disable_crash_handler() const;
+
OS_Windows(HINSTANCE _hInstance);
~OS_Windows();
};