Added support for vertical syncing via the Windows OS compositor (DWM.)
This commit is contained in:
parent
10481046e5
commit
e1dda5195c
11 changed files with 108 additions and 4 deletions
|
@ -584,6 +584,15 @@ bool _OS::is_vsync_enabled() const {
|
|||
return OS::get_singleton()->is_vsync_enabled();
|
||||
}
|
||||
|
||||
void _OS::set_vsync_via_compositor(bool p_enable) {
|
||||
OS::get_singleton()->set_vsync_via_compositor(p_enable);
|
||||
}
|
||||
|
||||
bool _OS::is_vsync_via_compositor_enabled() const {
|
||||
|
||||
return OS::get_singleton()->is_vsync_via_compositor_enabled();
|
||||
}
|
||||
|
||||
_OS::PowerState _OS::get_power_state() {
|
||||
return _OS::PowerState(OS::get_singleton()->get_power_state());
|
||||
}
|
||||
|
@ -1335,6 +1344,9 @@ void _OS::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_use_vsync", "enable"), &_OS::set_use_vsync);
|
||||
ClassDB::bind_method(D_METHOD("is_vsync_enabled"), &_OS::is_vsync_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_vsync_via_compositor", "enable"), &_OS::set_vsync_via_compositor);
|
||||
ClassDB::bind_method(D_METHOD("is_vsync_via_compositor_enabled"), &_OS::is_vsync_via_compositor_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("has_feature", "tag_name"), &_OS::has_feature);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_power_state"), &_OS::get_power_state);
|
||||
|
@ -1349,6 +1361,7 @@ void _OS::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::INT, "current_screen"), "set_current_screen", "get_current_screen");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "exit_code"), "set_exit_code", "get_exit_code");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vsync_enabled"), "set_use_vsync", "is_vsync_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vsync_via_compositor"), "set_vsync_via_compositor", "is_vsync_via_compositor_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "low_processor_usage_mode"), "set_low_processor_usage_mode", "is_in_low_processor_usage_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "low_processor_usage_mode_sleep_usec"), "set_low_processor_usage_mode_sleep_usec", "get_low_processor_usage_mode_sleep_usec");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_screen_on"), "set_keep_screen_on", "is_keep_screen_on");
|
||||
|
@ -1371,6 +1384,7 @@ void _OS::_bind_methods() {
|
|||
ADD_PROPERTY_DEFAULT("current_screen", 0);
|
||||
ADD_PROPERTY_DEFAULT("exit_code", 0);
|
||||
ADD_PROPERTY_DEFAULT("vsync_enabled", true);
|
||||
ADD_PROPERTY_DEFAULT("vsync_via_compositor", false);
|
||||
ADD_PROPERTY_DEFAULT("low_processor_usage_mode", false);
|
||||
ADD_PROPERTY_DEFAULT("low_processor_usage_mode_sleep_usec", 6900);
|
||||
ADD_PROPERTY_DEFAULT("keep_screen_on", true);
|
||||
|
|
|
@ -345,6 +345,9 @@ public:
|
|||
void set_use_vsync(bool p_enable);
|
||||
bool is_vsync_enabled() const;
|
||||
|
||||
void set_vsync_via_compositor(bool p_enable);
|
||||
bool is_vsync_via_compositor_enabled() const;
|
||||
|
||||
PowerState get_power_state();
|
||||
int get_power_seconds_left();
|
||||
int get_power_percent_left();
|
||||
|
|
|
@ -572,6 +572,14 @@ bool OS::is_vsync_enabled() const {
|
|||
return _use_vsync;
|
||||
}
|
||||
|
||||
void OS::set_vsync_via_compositor(bool p_enable) {
|
||||
_vsync_via_compositor = p_enable;
|
||||
}
|
||||
|
||||
bool OS::is_vsync_via_compositor_enabled() const {
|
||||
return _vsync_via_compositor;
|
||||
}
|
||||
|
||||
OS::PowerState OS::get_power_state() {
|
||||
return POWERSTATE_UNKNOWN;
|
||||
}
|
||||
|
|
10
core/os/os.h
10
core/os/os.h
|
@ -60,6 +60,9 @@ class OS {
|
|||
bool _allow_hidpi;
|
||||
bool _allow_layered;
|
||||
bool _use_vsync;
|
||||
bool _vsync_via_compositor;
|
||||
|
||||
char *last_error;
|
||||
|
||||
void *_stack_bottom;
|
||||
|
||||
|
@ -98,9 +101,10 @@ public:
|
|||
bool maximized;
|
||||
bool always_on_top;
|
||||
bool use_vsync;
|
||||
bool vsync_via_compositor;
|
||||
bool layered;
|
||||
float get_aspect() const { return (float)width / (float)height; }
|
||||
VideoMode(int p_width = 1024, int p_height = 600, bool p_fullscreen = false, bool p_resizable = true, bool p_borderless_window = false, bool p_maximized = false, bool p_always_on_top = false, bool p_use_vsync = false) {
|
||||
VideoMode(int p_width = 1024, int p_height = 600, bool p_fullscreen = false, bool p_resizable = true, bool p_borderless_window = false, bool p_maximized = false, bool p_always_on_top = false, bool p_use_vsync = false, bool p_vsync_via_compositor = false) {
|
||||
width = p_width;
|
||||
height = p_height;
|
||||
fullscreen = p_fullscreen;
|
||||
|
@ -109,6 +113,7 @@ public:
|
|||
maximized = p_maximized;
|
||||
always_on_top = p_always_on_top;
|
||||
use_vsync = p_use_vsync;
|
||||
vsync_via_compositor = p_vsync_via_compositor;
|
||||
layered = false;
|
||||
}
|
||||
};
|
||||
|
@ -507,6 +512,9 @@ public:
|
|||
//real, actual overridable function to switch vsync, which needs to be called from graphics thread if needed
|
||||
virtual void _set_use_vsync(bool p_enable) {}
|
||||
|
||||
void set_vsync_via_compositor(bool p_enable);
|
||||
bool is_vsync_via_compositor_enabled() const;
|
||||
|
||||
virtual OS::PowerState get_power_state();
|
||||
virtual int get_power_seconds_left();
|
||||
virtual int get_power_percent_left();
|
||||
|
|
|
@ -928,6 +928,9 @@
|
|||
<member name="vsync_enabled" type="bool" setter="set_use_vsync" getter="is_vsync_enabled" default="true">
|
||||
If [code]true[/code], vertical synchronization (Vsync) is enabled.
|
||||
</member>
|
||||
<member name="vsync_via_compositor" type="bool" setter="set_vsync_via_compositor" getter="is_vsync_via_compositor_enabled" default="false">
|
||||
If [code]true[/code] and [code]vsync_enabled[/code] is true, the operating system's window compositor will be used for vsync when the compositor is enabled and the game is in windowed mode.
|
||||
</member>
|
||||
<member name="window_borderless" type="bool" setter="set_borderless_window" getter="get_borderless_window" default="false">
|
||||
If [code]true[/code], removes the window frame.
|
||||
[b]Note:[/b] Setting [code]window_borderless[/code] to [code]false[/code] disables per-pixel transparency.
|
||||
|
|
|
@ -431,6 +431,9 @@
|
|||
<member name="display/window/vsync/use_vsync" type="bool" setter="" getter="" default="true">
|
||||
If [code]true[/code], enables vertical synchronization. This eliminates tearing that may appear in moving scenes, at the cost of higher input latency and stuttering at lower framerates. If [code]false[/code], vertical synchronization will be disabled, however, many platforms will enforce it regardless (such as mobile platforms and HTML5).
|
||||
</member>
|
||||
<member name="display/window/vsync/vsync_via_compositor" type="bool" setter="" getter="" default="false">
|
||||
If [code]Use Vsync[/code] is enabled and this setting is [code]true[/code], enables vertical synchronization via the operating system's window compositor when in windowed mode and the compositor is enabled. This will prevent stutter in certain situations. (Windows only.)
|
||||
</member>
|
||||
<member name="editor/script_templates_search_path" type="String" setter="" getter="" default=""res://script_templates"">
|
||||
</member>
|
||||
<member name="editor/search_in_file_extensions" type="PoolStringArray" setter="" getter="" default="PoolStringArray( "gd", "shader" )">
|
||||
|
|
|
@ -259,6 +259,8 @@ void Main::print_help(const char *p_binary) {
|
|||
OS::get_singleton()->print(" --position <X>,<Y> Request window position.\n");
|
||||
OS::get_singleton()->print(" --low-dpi Force low-DPI mode (macOS and Windows only).\n");
|
||||
OS::get_singleton()->print(" --no-window Disable window creation (Windows only). Useful together with --script.\n");
|
||||
OS::get_singleton()->print(" --enable-vsync-via-compositor When vsync is enabled, vsync via the OS' window compositor (Windows only).\n");
|
||||
OS::get_singleton()->print(" --disable-vsync-via-compositor Disable vsync via the OS' window compositor (Windows only).\n");
|
||||
OS::get_singleton()->print("\n");
|
||||
#endif
|
||||
|
||||
|
@ -399,6 +401,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
Vector<String> breakpoints;
|
||||
bool use_custom_res = true;
|
||||
bool force_res = false;
|
||||
bool saw_vsync_via_compositor_override = false;
|
||||
#ifdef TOOLS_ENABLED
|
||||
bool found_project = false;
|
||||
#endif
|
||||
|
@ -590,6 +593,14 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
} else if (I->get() == "--no-window") { // disable window creation (Windows only)
|
||||
|
||||
OS::get_singleton()->set_no_window_mode(true);
|
||||
} else if (I->get() == "--enable-vsync-via-compositor") {
|
||||
|
||||
video_mode.vsync_via_compositor = true;
|
||||
saw_vsync_via_compositor_override = true;
|
||||
} else if (I->get() == "--disable-vsync-via-compositor") {
|
||||
|
||||
video_mode.vsync_via_compositor = false;
|
||||
saw_vsync_via_compositor_override = true;
|
||||
#endif
|
||||
} else if (I->get() == "--profiling") { // enable profiling
|
||||
|
||||
|
@ -1009,6 +1020,16 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
video_mode.use_vsync = GLOBAL_DEF_RST("display/window/vsync/use_vsync", true);
|
||||
OS::get_singleton()->_use_vsync = video_mode.use_vsync;
|
||||
|
||||
if (!saw_vsync_via_compositor_override) {
|
||||
// If one of the command line options to enable/disable vsync via the
|
||||
// window compositor ("--enable-vsync-via-compositor" or
|
||||
// "--disable-vsync-via-compositor") was present then it overrides the
|
||||
// project setting.
|
||||
video_mode.vsync_via_compositor = GLOBAL_DEF("display/window/vsync/vsync_via_compositor", false);
|
||||
}
|
||||
|
||||
OS::get_singleton()->_vsync_via_compositor = video_mode.vsync_via_compositor;
|
||||
|
||||
OS::get_singleton()->_allow_layered = GLOBAL_DEF("display/window/per_pixel_transparency/allowed", false);
|
||||
video_mode.layered = GLOBAL_DEF("display/window/per_pixel_transparency/enabled", false);
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
|
||||
#include "context_gl_windows.h"
|
||||
|
||||
#include <dwmapi.h>
|
||||
|
||||
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
|
||||
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
|
||||
#define WGL_CONTEXT_FLAGS_ARB 0x2094
|
||||
|
@ -63,16 +65,52 @@ int ContextGL_Windows::get_window_height() {
|
|||
return OS::get_singleton()->get_video_mode().height;
|
||||
}
|
||||
|
||||
bool ContextGL_Windows::should_vsync_via_compositor() {
|
||||
|
||||
if (OS::get_singleton()->is_window_fullscreen() || !OS::get_singleton()->is_vsync_via_compositor_enabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Note: All Windows versions supported by Godot have a compositor.
|
||||
// It can be disabled on earlier Windows versions.
|
||||
BOOL dwm_enabled;
|
||||
|
||||
if (SUCCEEDED(DwmIsCompositionEnabled(&dwm_enabled))) {
|
||||
return dwm_enabled;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ContextGL_Windows::swap_buffers() {
|
||||
|
||||
SwapBuffers(hDC);
|
||||
|
||||
if (use_vsync) {
|
||||
bool vsync_via_compositor_now = should_vsync_via_compositor();
|
||||
|
||||
if (vsync_via_compositor_now) {
|
||||
DwmFlush();
|
||||
}
|
||||
|
||||
if (vsync_via_compositor_now != vsync_via_compositor) {
|
||||
// The previous frame had a different operating mode than this
|
||||
// frame. Set the 'vsync_via_compositor' member variable and the
|
||||
// OpenGL swap interval to their proper values.
|
||||
set_use_vsync(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContextGL_Windows::set_use_vsync(bool p_use) {
|
||||
|
||||
vsync_via_compositor = p_use && should_vsync_via_compositor();
|
||||
|
||||
if (wglSwapIntervalEXT) {
|
||||
wglSwapIntervalEXT(p_use ? 1 : 0);
|
||||
int swap_interval = (p_use && !vsync_via_compositor) ? 1 : 0;
|
||||
wglSwapIntervalEXT(swap_interval);
|
||||
}
|
||||
|
||||
use_vsync = p_use;
|
||||
}
|
||||
|
||||
|
@ -177,6 +215,7 @@ ContextGL_Windows::ContextGL_Windows(HWND hwnd, bool p_opengl_3_context) {
|
|||
opengl_3_context = p_opengl_3_context;
|
||||
hWnd = hwnd;
|
||||
use_vsync = false;
|
||||
vsync_via_compositor = false;
|
||||
}
|
||||
|
||||
ContextGL_Windows::~ContextGL_Windows() {
|
||||
|
|
|
@ -50,9 +50,12 @@ class ContextGL_Windows {
|
|||
HWND hWnd;
|
||||
bool opengl_3_context;
|
||||
bool use_vsync;
|
||||
bool vsync_via_compositor;
|
||||
|
||||
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
|
||||
|
||||
static bool should_vsync_via_compositor();
|
||||
|
||||
public:
|
||||
void release_current();
|
||||
|
||||
|
|
|
@ -221,7 +221,8 @@ def configure_msvc(env, manual_msvc_config):
|
|||
|
||||
LIBS = ['winmm', 'opengl32', 'dsound', 'kernel32', 'ole32', 'oleaut32',
|
||||
'user32', 'gdi32', 'IPHLPAPI', 'Shlwapi', 'wsock32', 'Ws2_32',
|
||||
'shell32', 'advapi32', 'dinput8', 'dxguid', 'imm32', 'bcrypt','Avrt']
|
||||
'shell32', 'advapi32', 'dinput8', 'dxguid', 'imm32', 'bcrypt','Avrt',
|
||||
'dwmapi']
|
||||
env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in LIBS])
|
||||
|
||||
if manual_msvc_config:
|
||||
|
@ -348,7 +349,7 @@ def configure_mingw(env):
|
|||
env.Append(CCFLAGS=['-mwindows'])
|
||||
env.Append(CPPDEFINES=['WINDOWS_ENABLED', 'OPENGL_ENABLED', 'WASAPI_ENABLED', 'WINMIDI_ENABLED'])
|
||||
env.Append(CPPDEFINES=[('WINVER', env['target_win_version']), ('_WIN32_WINNT', env['target_win_version'])])
|
||||
env.Append(LIBS=['mingw32', 'opengl32', 'dsound', 'ole32', 'd3d9', 'winmm', 'gdi32', 'iphlpapi', 'shlwapi', 'wsock32', 'ws2_32', 'kernel32', 'oleaut32', 'dinput8', 'dxguid', 'ksuser', 'imm32', 'bcrypt', 'avrt', 'uuid'])
|
||||
env.Append(LIBS=['mingw32', 'opengl32', 'dsound', 'ole32', 'd3d9', 'winmm', 'gdi32', 'iphlpapi', 'shlwapi', 'wsock32', 'ws2_32', 'kernel32', 'oleaut32', 'dinput8', 'dxguid', 'ksuser', 'imm32', 'bcrypt', 'avrt', 'uuid', 'dwmapi'])
|
||||
|
||||
env.Append(CPPDEFINES=['MINGW_ENABLED', ('MINGW_HAS_SECURE_API', 1)])
|
||||
|
||||
|
|
|
@ -1480,6 +1480,7 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
|
|||
video_driver_index = p_video_driver;
|
||||
|
||||
gl_context->set_use_vsync(video_mode.use_vsync);
|
||||
set_vsync_via_compositor(video_mode.vsync_via_compositor);
|
||||
#endif
|
||||
|
||||
visual_server = memnew(VisualServerRaster);
|
||||
|
|
Loading…
Reference in a new issue