Merge pull request #48622 from Geometror/reimplement-disableable-vsync

This commit is contained in:
Hugo Locurcio 2021-07-10 01:02:23 +02:00 committed by GitHub
commit a2d5f191d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 309 additions and 256 deletions

View File

@ -1114,6 +1114,7 @@ ProjectSettings::ProjectSettings() {
// Keep the enum values in sync with the `DisplayServer::ScreenOrientation` enum. // Keep the enum values in sync with the `DisplayServer::ScreenOrientation` enum.
custom_prop_info["display/window/handheld/orientation"] = PropertyInfo(Variant::INT, "display/window/handheld/orientation", PROPERTY_HINT_ENUM, "Landscape,Portrait,Reverse Landscape,Reverse Portrait,Sensor Landscape,Sensor Portrait,Sensor"); custom_prop_info["display/window/handheld/orientation"] = PropertyInfo(Variant::INT, "display/window/handheld/orientation", PROPERTY_HINT_ENUM, "Landscape,Portrait,Reverse Landscape,Reverse Portrait,Sensor Landscape,Sensor Portrait,Sensor");
custom_prop_info["display/window/vsync/vsync_mode"] = PropertyInfo(Variant::STRING, "display/window/vsync/vsync_mode", PROPERTY_HINT_ENUM, "Disabled,Enabled,Adaptive,Mailbox");
custom_prop_info["rendering/driver/threads/thread_model"] = PropertyInfo(Variant::INT, "rendering/driver/threads/thread_model", PROPERTY_HINT_ENUM, "Single-Unsafe,Single-Safe,Multi-Threaded"); custom_prop_info["rendering/driver/threads/thread_model"] = PropertyInfo(Variant::INT, "rendering/driver/threads/thread_model", PROPERTY_HINT_ENUM, "Single-Unsafe,Single-Safe,Multi-Threaded");
GLOBAL_DEF("physics/2d/run_on_thread", false); GLOBAL_DEF("physics/2d/run_on_thread", false);
GLOBAL_DEF("physics/3d/run_on_thread", false); GLOBAL_DEF("physics/3d/run_on_thread", false);

View File

@ -58,8 +58,6 @@ class OS {
int _orientation; int _orientation;
bool _allow_hidpi = false; bool _allow_hidpi = false;
bool _allow_layered = false; bool _allow_layered = false;
bool _use_vsync;
bool _vsync_via_compositor;
bool _stdout_enabled = true; bool _stdout_enabled = true;
bool _stderr_enabled = true; bool _stderr_enabled = true;

View File

@ -44,9 +44,11 @@
</return> </return>
<argument index="0" name="mode" type="int" enum="DisplayServer.WindowMode"> <argument index="0" name="mode" type="int" enum="DisplayServer.WindowMode">
</argument> </argument>
<argument index="1" name="flags" type="int"> <argument index="1" name="vsync_mode" type="int" enum="DisplayServer.VSyncMode">
</argument> </argument>
<argument index="2" name="rect" type="Rect2i" default="Rect2i(0, 0, 0, 0)"> <argument index="2" name="flags" type="int">
</argument>
<argument index="3" name="rect" type="Rect2i" default="Rect2i(0, 0, 0, 0)">
</argument> </argument>
<description> <description>
</description> </description>
@ -671,34 +673,6 @@
[b]Note:[/b] This method is implemented on Android, iOS and UWP. [b]Note:[/b] This method is implemented on Android, iOS and UWP.
</description> </description>
</method> </method>
<method name="vsync_is_enabled" qualifiers="const">
<return type="bool">
</return>
<description>
</description>
</method>
<method name="vsync_is_using_via_compositor" qualifiers="const">
<return type="bool">
</return>
<description>
</description>
</method>
<method name="vsync_set_enabled">
<return type="void">
</return>
<argument index="0" name="enabled" type="bool">
</argument>
<description>
</description>
</method>
<method name="vsync_set_use_via_compositor">
<return type="void">
</return>
<argument index="0" name="enabled" type="bool">
</argument>
<description>
</description>
</method>
<method name="window_attach_instance_id"> <method name="window_attach_instance_id">
<return type="void"> <return type="void">
</return> </return>
@ -791,6 +765,15 @@
<description> <description>
</description> </description>
</method> </method>
<method name="window_get_vsync_mode" qualifiers="const">
<return type="int" enum="DisplayServer.VSyncMode">
</return>
<argument index="0" name="window_id" type="int" default="0">
</argument>
<description>
Returns the VSync mode of the given window.
</description>
</method>
<method name="window_move_to_foreground"> <method name="window_move_to_foreground">
<return type="void"> <return type="void">
</return> </return>
@ -995,6 +978,19 @@
<description> <description>
</description> </description>
</method> </method>
<method name="window_set_vsync_mode">
<return type="void">
</return>
<argument index="0" name="vsync_mode" type="int" enum="DisplayServer.VSyncMode">
</argument>
<argument index="1" name="window_id" type="int" default="0">
</argument>
<description>
Sets the VSync mode of the given window.
See [enum DisplayServer.VSyncMode] for possible values and how they affect the behavior of your application.
Depending on the platform and used renderer, the engine will fall back to [constant VSYNC_ENABLED], if the desired mode is not supported.
</description>
</method>
<method name="window_set_window_event_callback"> <method name="window_set_window_event_callback">
<return type="void"> <return type="void">
</return> </return>
@ -1151,5 +1147,18 @@
</constant> </constant>
<constant name="WINDOW_EVENT_DPI_CHANGE" value="6" enum="WindowEvent"> <constant name="WINDOW_EVENT_DPI_CHANGE" value="6" enum="WindowEvent">
</constant> </constant>
<constant name="VSYNC_DISABLED" value="0" enum="VSyncMode">
No vertical synchronization, which means the engine will display frames as fast as possible (tearing may be visible).
</constant>
<constant name="VSYNC_ENABLED" value="1" enum="VSyncMode">
Default vertical synchronization mode, the image is displayed only on vertical blanking intervals (no tearing is visible).
</constant>
<constant name="VSYNC_ADAPTIVE" value="2" enum="VSyncMode">
Behaves like [constant VSYNC_DISABLED] when the framerate drops below the screen's refresh rate to reduce stuttering (tearing may be visible), otherwise vertical synchronization is enabled to avoid tearing.
</constant>
<constant name="VSYNC_MAILBOX" value="3" enum="VSyncMode">
Displays the most recent image in the queue on vertical blanking intervals, while rendering to the other images (no tearing is visible).
Although not guaranteed, the images can be rendered as fast as possible, which may reduce input lag.
</constant>
</constants> </constants>
</class> </class>

View File

@ -445,7 +445,7 @@
</member> </member>
<member name="debug/settings/fps/force_fps" type="int" setter="" getter="" default="0"> <member name="debug/settings/fps/force_fps" type="int" setter="" getter="" default="0">
Maximum number of frames per second allowed. The actual number of frames per second may still be below this value if the game is lagging. Maximum number of frames per second allowed. The actual number of frames per second may still be below this value if the game is lagging.
If [member display/window/vsync/use_vsync] is enabled, it takes precedence and the forced FPS number cannot exceed the monitor's refresh rate. If [member display/window/vsync/vsync_mode] is set to [code]Enabled[/code] or [code]Adaptive[/code], it takes precedence and the forced FPS number cannot exceed the monitor's refresh rate.
This setting is therefore mostly relevant for lowering the maximum FPS below VSync, e.g. to perform non-real-time rendering of static frames, or test the project under lag conditions. This setting is therefore mostly relevant for lowering the maximum FPS below VSync, e.g. to perform non-real-time rendering of static frames, or test the project under lag conditions.
</member> </member>
<member name="debug/settings/gdscript/max_call_stack" type="int" setter="" getter="" default="1024"> <member name="debug/settings/gdscript/max_call_stack" type="int" setter="" getter="" default="1024">
@ -532,12 +532,10 @@
<member name="display/window/size/width" type="int" setter="" getter="" default="1024"> <member name="display/window/size/width" type="int" setter="" getter="" default="1024">
Sets the game's main viewport width. On desktop platforms, this is the default window size. Stretch mode settings also use this as a reference when enabled. Sets the game's main viewport width. On desktop platforms, this is the default window size. Stretch mode settings also use this as a reference when enabled.
</member> </member>
<member name="display/window/vsync/use_vsync" type="bool" setter="" getter="" default="true"> <member name="display/window/vsync/vsync_mode" type="String" setter="" getter="" default="&quot;Enabled&quot;">
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). Sets the VSync mode for the main game window.
</member> See [enum DisplayServer.VSyncMode] for possible values and how they affect the behavior of your application.
<member name="display/window/vsync/vsync_via_compositor" type="bool" setter="" getter="" default="false"> Depending on the platform and used renderer, the engine will fall back to [code]Enabled[/code], if the desired mode is not supported.
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.)
[b]Note:[/b] This option is experimental and meant to alleviate stutter experienced by some users. However, some users have experienced a Vsync framerate halving (e.g. from 60 FPS to 30 FPS) when using it.
</member> </member>
<member name="editor/node_naming/name_casing" type="int" setter="" getter="" default="0"> <member name="editor/node_naming/name_casing" type="int" setter="" getter="" default="0">
When creating node names automatically, set the type of casing in this project. This is mostly an editor setting. When creating node names automatically, set the type of casing in this project. This is mostly an editor setting.

View File

@ -1189,7 +1189,7 @@ bool VulkanContext::_use_validation_layers() {
return Engine::get_singleton()->is_validation_layers_enabled(); return Engine::get_singleton()->is_validation_layers_enabled();
} }
Error VulkanContext::_window_create(DisplayServer::WindowID p_window_id, VkSurfaceKHR p_surface, int p_width, int p_height) { Error VulkanContext::_window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, VkSurfaceKHR p_surface, int p_width, int p_height) {
ERR_FAIL_COND_V(windows.has(p_window_id), ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(windows.has(p_window_id), ERR_INVALID_PARAMETER);
if (!queues_initialized) { if (!queues_initialized) {
@ -1217,6 +1217,7 @@ Error VulkanContext::_window_create(DisplayServer::WindowID p_window_id, VkSurfa
window.surface = p_surface; window.surface = p_surface;
window.width = p_width; window.width = p_width;
window.height = p_height; window.height = p_height;
window.vsync_mode = p_vsync_mode;
Error err = _update_swap_chain(&window); Error err = _update_swap_chain(&window);
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE); ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
@ -1360,7 +1361,6 @@ Error VulkanContext::_update_swap_chain(Window *window) {
} }
// The FIFO present mode is guaranteed by the spec to be supported // The FIFO present mode is guaranteed by the spec to be supported
// and to have no tearing. It's a great default present mode to use. // and to have no tearing. It's a great default present mode to use.
VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
// There are times when you may wish to use another present mode. The // There are times when you may wish to use another present mode. The
// following code shows how to select them, and the comments provide some // following code shows how to select them, and the comments provide some
@ -1389,16 +1389,41 @@ Error VulkanContext::_update_swap_chain(Window *window) {
// the application wants the late image to be immediately displayed, even // the application wants the late image to be immediately displayed, even
// though that may mean some tearing. // though that may mean some tearing.
if (window->presentMode != swapchainPresentMode) { VkPresentModeKHR requested_present_mode = VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR;
for (size_t i = 0; i < presentModeCount; ++i) { switch (window->vsync_mode) {
if (presentModes[i] == window->presentMode) { case DisplayServer::VSYNC_MAILBOX:
swapchainPresentMode = window->presentMode; requested_present_mode = VkPresentModeKHR::VK_PRESENT_MODE_MAILBOX_KHR;
break; break;
} case DisplayServer::VSYNC_ADAPTIVE:
requested_present_mode = VkPresentModeKHR::VK_PRESENT_MODE_FIFO_RELAXED_KHR;
break;
case DisplayServer::VSYNC_ENABLED:
requested_present_mode = VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR;
break;
case DisplayServer::VSYNC_DISABLED:
requested_present_mode = VkPresentModeKHR::VK_PRESENT_MODE_IMMEDIATE_KHR;
break;
}
// Check if the requested mode is available.
bool present_mode_available = false;
for (uint32_t i = 0; i < presentModeCount; i++) {
if (presentModes[i] == requested_present_mode) {
present_mode_available = true;
} }
} }
// Set the windows present mode if it is available, otherwise FIFO is used (guaranteed supported).
if (present_mode_available) {
window->presentMode = requested_present_mode;
} else {
WARN_PRINT("Requested VSync mode is not available!");
window->vsync_mode = DisplayServer::VSYNC_ENABLED; //Set to default
}
print_verbose("Using present mode: " + String(string_VkPresentModeKHR(window->presentMode)));
free(presentModes); free(presentModes);
ERR_FAIL_COND_V_MSG(swapchainPresentMode != window->presentMode, ERR_CANT_CREATE, "Present mode specified is not supported\n");
// Determine the number of VkImages to use in the swap chain. // Determine the number of VkImages to use in the swap chain.
// Application desires to acquire 3 images at a time for triple // Application desires to acquire 3 images at a time for triple
@ -1455,7 +1480,7 @@ Error VulkanContext::_update_swap_chain(Window *window) {
/*pQueueFamilyIndices*/ nullptr, /*pQueueFamilyIndices*/ nullptr,
/*preTransform*/ (VkSurfaceTransformFlagBitsKHR)preTransform, /*preTransform*/ (VkSurfaceTransformFlagBitsKHR)preTransform,
/*compositeAlpha*/ compositeAlpha, /*compositeAlpha*/ compositeAlpha,
/*presentMode*/ swapchainPresentMode, /*presentMode*/ window->presentMode,
/*clipped*/ true, /*clipped*/ true,
/*oldSwapchain*/ VK_NULL_HANDLE, /*oldSwapchain*/ VK_NULL_HANDLE,
}; };
@ -2162,6 +2187,17 @@ String VulkanContext::get_device_pipeline_cache_uuid() const {
return pipeline_cache_id; return pipeline_cache_id;
} }
DisplayServer::VSyncMode VulkanContext::get_vsync_mode(DisplayServer::WindowID p_window) const {
ERR_FAIL_COND_V_MSG(!windows.has(p_window), DisplayServer::VSYNC_ENABLED, "Could not get VSync mode for window with WindowID " + itos(p_window) + " because it does not exist.");
return windows[p_window].vsync_mode;
}
void VulkanContext::set_vsync_mode(DisplayServer::WindowID p_window, DisplayServer::VSyncMode p_mode) {
ERR_FAIL_COND_MSG(!windows.has(p_window), "Could not set VSync mode for window with WindowID " + itos(p_window) + " because it does not exist.");
windows[p_window].vsync_mode = p_mode;
_update_swap_chain(&windows[p_window]);
}
VulkanContext::VulkanContext() { VulkanContext::VulkanContext() {
command_buffer_queue.resize(1); // First one is always the setup command. command_buffer_queue.resize(1); // First one is always the setup command.
command_buffer_queue.write[0] = nullptr; command_buffer_queue.write[0] = nullptr;

View File

@ -124,6 +124,7 @@ private:
uint32_t current_buffer = 0; uint32_t current_buffer = 0;
int width = 0; int width = 0;
int height = 0; int height = 0;
DisplayServer::VSyncMode vsync_mode = DisplayServer::VSYNC_ENABLED;
VkCommandPool present_cmd_pool = VK_NULL_HANDLE; // For separate present queue. VkCommandPool present_cmd_pool = VK_NULL_HANDLE; // For separate present queue.
VkRenderPass render_pass = VK_NULL_HANDLE; VkRenderPass render_pass = VK_NULL_HANDLE;
}; };
@ -222,7 +223,7 @@ private:
protected: protected:
virtual const char *_get_platform_surface_extension() const = 0; virtual const char *_get_platform_surface_extension() const = 0;
virtual Error _window_create(DisplayServer::WindowID p_window_id, VkSurfaceKHR p_surface, int p_width, int p_height); virtual Error _window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, VkSurfaceKHR p_surface, int p_width, int p_height);
virtual bool _use_validation_layers(); virtual bool _use_validation_layers();
@ -276,6 +277,9 @@ public:
String get_device_name() const; String get_device_name() const;
String get_device_pipeline_cache_uuid() const; String get_device_pipeline_cache_uuid() const;
void set_vsync_mode(DisplayServer::WindowID p_window, DisplayServer::VSyncMode p_mode);
DisplayServer::VSyncMode get_vsync_mode(DisplayServer::WindowID p_window = 0) const;
VulkanContext(); VulkanContext();
virtual ~VulkanContext(); virtual ~VulkanContext();
}; };

View File

@ -151,9 +151,9 @@ static bool auto_build_solutions = false;
static DisplayServer::WindowMode window_mode = DisplayServer::WINDOW_MODE_WINDOWED; static DisplayServer::WindowMode window_mode = DisplayServer::WINDOW_MODE_WINDOWED;
static DisplayServer::ScreenOrientation window_orientation = DisplayServer::SCREEN_LANDSCAPE; static DisplayServer::ScreenOrientation window_orientation = DisplayServer::SCREEN_LANDSCAPE;
static DisplayServer::VSyncMode window_vsync_mode = DisplayServer::VSYNC_ENABLED;
static uint32_t window_flags = 0; static uint32_t window_flags = 0;
static Size2i window_size = Size2i(1024, 600); static Size2i window_size = Size2i(1024, 600);
static bool window_vsync_via_compositor = false;
static int init_screen = -1; static int init_screen = -1;
static bool init_fullscreen = false; static bool init_fullscreen = false;
@ -338,8 +338,6 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print(" --position <X>,<Y> Request window position.\n"); 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(" --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(" --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(" --single-window Use a single window (no separate subwindows).\n"); OS::get_singleton()->print(" --single-window Use a single window (no separate subwindows).\n");
OS::get_singleton()->print(" --tablet-driver Pen tablet input driver.\n"); OS::get_singleton()->print(" --tablet-driver Pen tablet input driver.\n");
OS::get_singleton()->print("\n"); OS::get_singleton()->print("\n");
@ -599,11 +597,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
Vector<String> breakpoints; Vector<String> breakpoints;
bool use_custom_res = true; bool use_custom_res = true;
bool force_res = false; bool force_res = false;
bool saw_vsync_via_compositor_override = false;
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
bool found_project = false; bool found_project = false;
#endif #endif
bool use_vsync = false;
packed_data = PackedData::get_singleton(); packed_data = PackedData::get_singleton();
if (!packed_data) { if (!packed_data) {
@ -825,12 +821,6 @@ 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) } else if (I->get() == "--no-window") { // disable window creation (Windows only)
OS::get_singleton()->set_no_window_mode(true); OS::get_singleton()->set_no_window_mode(true);
} else if (I->get() == "--enable-vsync-via-compositor") {
window_vsync_via_compositor = true;
saw_vsync_via_compositor_override = true;
} else if (I->get() == "--disable-vsync-via-compositor") {
window_vsync_via_compositor = false;
saw_vsync_via_compositor_override = true;
#endif #endif
} else if (I->get() == "--profiling") { // enable profiling } else if (I->get() == "--profiling") { // enable profiling
@ -1287,19 +1277,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->_allow_hidpi = GLOBAL_DEF("display/window/dpi/allow_hidpi", false); OS::get_singleton()->_allow_hidpi = GLOBAL_DEF("display/window/dpi/allow_hidpi", false);
} }
use_vsync = GLOBAL_DEF_RST("display/window/vsync/use_vsync", true);
OS::get_singleton()->_use_vsync = 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.
window_vsync_via_compositor = GLOBAL_DEF("display/window/vsync/vsync_via_compositor", false);
}
OS::get_singleton()->_vsync_via_compositor = window_vsync_via_compositor;
/* todo restore /* todo restore
OS::get_singleton()->_allow_layered = GLOBAL_DEF("display/window/per_pixel_transparency/allowed", false); 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); video_mode.layered = GLOBAL_DEF("display/window/per_pixel_transparency/enabled", false);
@ -1357,7 +1334,22 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
{ {
window_orientation = DisplayServer::ScreenOrientation(int(GLOBAL_DEF_BASIC("display/window/handheld/orientation", DisplayServer::ScreenOrientation::SCREEN_LANDSCAPE))); window_orientation = DisplayServer::ScreenOrientation(int(GLOBAL_DEF_BASIC("display/window/handheld/orientation", DisplayServer::ScreenOrientation::SCREEN_LANDSCAPE)));
} }
{
String vsync_mode = GLOBAL_DEF("display/window/vsync/vsync_mode", "Enabled");
if (vsync_mode == "Disabled") {
window_vsync_mode = DisplayServer::VSYNC_DISABLED;
} else if (vsync_mode == "Enabled") {
window_vsync_mode = DisplayServer::VSYNC_ENABLED;
} else if (vsync_mode == "Adaptive") {
window_vsync_mode = DisplayServer::VSYNC_ADAPTIVE;
} else if (vsync_mode == "Mailbox") {
window_vsync_mode = DisplayServer::VSYNC_MAILBOX;
} else {
WARN_PRINT("VSync mode unknown.");
window_vsync_mode = DisplayServer::VSYNC_ENABLED;
}
}
Engine::get_singleton()->set_iterations_per_second(GLOBAL_DEF_BASIC("physics/common/physics_fps", 60)); Engine::get_singleton()->set_iterations_per_second(GLOBAL_DEF_BASIC("physics/common/physics_fps", 60));
ProjectSettings::get_singleton()->set_custom_property_info("physics/common/physics_fps", ProjectSettings::get_singleton()->set_custom_property_info("physics/common/physics_fps",
PropertyInfo(Variant::INT, "physics/common/physics_fps", PropertyInfo(Variant::INT, "physics/common/physics_fps",
@ -1550,14 +1542,14 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
String rendering_driver; // temp broken String rendering_driver; // temp broken
Error err; Error err;
display_server = DisplayServer::create(display_driver_idx, rendering_driver, window_mode, window_flags, window_size, err); display_server = DisplayServer::create(display_driver_idx, rendering_driver, window_mode, window_vsync_mode, window_flags, window_size, err);
if (err != OK || display_server == nullptr) { if (err != OK || display_server == nullptr) {
//ok i guess we can't use this display server, try other ones //ok i guess we can't use this display server, try other ones
for (int i = 0; i < DisplayServer::get_create_function_count(); i++) { for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
if (i == display_driver_idx) { if (i == display_driver_idx) {
continue; //don't try the same twice continue; //don't try the same twice
} }
display_server = DisplayServer::create(i, rendering_driver, window_mode, window_flags, window_size, err); display_server = DisplayServer::create(i, rendering_driver, window_mode, window_vsync_mode, window_flags, window_size, err);
if (err == OK && display_server != nullptr) { if (err == OK && display_server != nullptr) {
break; break;
} }

View File

@ -85,12 +85,6 @@ Force low\-DPI mode (macOS and Windows only).
.TP .TP
\fB\-\-no\-window\fR \fB\-\-no\-window\fR
Disable window creation (Windows only). Useful together with \fB\-\-script\fR. Disable window creation (Windows only). Useful together with \fB\-\-script\fR.
.TP
\fB\-\-enable\-vsync\-via\-compositor\fR
When vsync is enabled, vsync via the OS' window compositor (Windows only).
.TP
\fB\-\-disable\-vsync\-via\-compositor\fR
Disable vsync via the OS' window compositor (Windows only).
.SS "Debug options:" .SS "Debug options:"
.TP .TP
\fB\-d\fR, \fB\-\-debug\fR \fB\-d\fR, \fB\-\-debug\fR

View File

@ -51,8 +51,6 @@ _arguments \
'--position[request window position]:position in X,Y format' \ '--position[request window position]:position in X,Y format' \
'--low-dpi[force low-DPI mode (macOS and Windows only)]' \ '--low-dpi[force low-DPI mode (macOS and Windows only)]' \
'--no-window[disable window creation (Windows only), useful together with --script]' \ '--no-window[disable window creation (Windows only), useful together with --script]' \
"--enable-vsync-via-compositor[when Vsync is enabled, Vsync via the OS' window compositor (Windows only)]" \
"--disable-vsync-via-compositor[disable Vsync via the OS' window compositor (Windows only)]" \
'(-d --debug)'{-d,--debug}'[debug (local stdout debugger)]' \ '(-d --debug)'{-d,--debug}'[debug (local stdout debugger)]' \
'(-b --breakpoints)'{-b,--breakpoints}'[specify the breakpoint list as source::line comma-separated pairs, no spaces (use %20 instead)]:breakpoint list' \ '(-b --breakpoints)'{-b,--breakpoints}'[specify the breakpoint list as source::line comma-separated pairs, no spaces (use %20 instead)]:breakpoint list' \
'--profiling[enable profiling in the script debugger]' \ '--profiling[enable profiling in the script debugger]' \

View File

@ -54,8 +54,6 @@ _complete_godot_options() {
--position --position
--low-dpi --low-dpi
--no-window --no-window
--enable-vsync-via-compositor
--disable-vsync-via-compositor
--debug --debug
--breakpoints --breakpoints
--profiling --profiling

View File

@ -61,8 +61,6 @@ complete -c godot -l resolution -d "Request window resolution" -x
complete -c godot -l position -d "Request window position" -x complete -c godot -l position -d "Request window position" -x
complete -c godot -l low-dpi -d "Force low-DPI mode (macOS and Windows only)" complete -c godot -l low-dpi -d "Force low-DPI mode (macOS and Windows only)"
complete -c godot -l no-window -d "Disable window creation (Windows only), useful together with --script" complete -c godot -l no-window -d "Disable window creation (Windows only), useful together with --script"
complete -c godot -l enable-vsync-via-compositor -d "When Vsync is enabled, Vsync via the OS' window compositor (Windows only)"
complete -c godot -l disable-vsync-via-compositor -d "Disable Vsync via the OS' window compositor (Windows only)"
# Debug options: # Debug options:
complete -c godot -s d -l debug -d "Debug (local stdout debugger)" complete -c godot -s d -l debug -d "Debug (local stdout debugger)"

View File

@ -358,8 +358,8 @@ Vector<String> DisplayServerAndroid::get_rendering_drivers_func() {
return drivers; return drivers;
} }
DisplayServer *DisplayServerAndroid::create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { DisplayServer *DisplayServerAndroid::create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerAndroid(p_rendering_driver, p_mode, p_flags, p_resolution, r_error)); DisplayServer *ds = memnew(DisplayServerAndroid(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
if (r_error != OK) { if (r_error != OK) {
ds->alert("Your video card driver does not support any of the supported Vulkan versions.", "Unable to initialize Video driver"); ds->alert("Your video card driver does not support any of the supported Vulkan versions.", "Unable to initialize Video driver");
} }
@ -377,10 +377,11 @@ void DisplayServerAndroid::reset_window() {
ERR_FAIL_COND(!native_window); ERR_FAIL_COND(!native_window);
ERR_FAIL_COND(!context_vulkan); ERR_FAIL_COND(!context_vulkan);
VSyncMode last_vsync_mode = context_vulkan->get_vsync_mode(MAIN_WINDOW_ID);
context_vulkan->window_destroy(MAIN_WINDOW_ID); context_vulkan->window_destroy(MAIN_WINDOW_ID);
Size2i display_size = OS_Android::get_singleton()->get_display_size(); Size2i display_size = OS_Android::get_singleton()->get_display_size();
if (context_vulkan->window_create(native_window, display_size.width, display_size.height) == -1) { if (context_vulkan->window_create(native_window, last_vsync_mode, display_size.width, display_size.height) == -1) {
memdelete(context_vulkan); memdelete(context_vulkan);
context_vulkan = nullptr; context_vulkan = nullptr;
ERR_FAIL_MSG("Failed to reset Vulkan window."); ERR_FAIL_MSG("Failed to reset Vulkan window.");
@ -402,7 +403,7 @@ void DisplayServerAndroid::notify_surface_changed(int p_width, int p_height) {
rect_changed_callback.call(reinterpret_cast<const Variant **>(&sizep), 1, ret, ce); rect_changed_callback.call(reinterpret_cast<const Variant **>(&sizep), 1, ret, ce);
} }
DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
rendering_driver = p_rendering_driver; rendering_driver = p_rendering_driver;
// TODO: rendering_driver is broken, change when different drivers are supported again // TODO: rendering_driver is broken, change when different drivers are supported again
@ -446,7 +447,7 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis
} }
Size2i display_size = OS_Android::get_singleton()->get_display_size(); Size2i display_size = OS_Android::get_singleton()->get_display_size();
if (context_vulkan->window_create(native_window, display_size.width, display_size.height) == -1) { if (context_vulkan->window_create(native_window, p_vsync_mode, display_size.width, display_size.height) == -1) {
memdelete(context_vulkan); memdelete(context_vulkan);
context_vulkan = nullptr; context_vulkan = nullptr;
ERR_FAIL_MSG("Failed to create Vulkan window."); ERR_FAIL_MSG("Failed to create Vulkan window.");
@ -901,3 +902,17 @@ void DisplayServerAndroid::cursor_set_shape(DisplayServer::CursorShape p_shape)
DisplayServer::CursorShape DisplayServerAndroid::cursor_get_shape() const { DisplayServer::CursorShape DisplayServerAndroid::cursor_get_shape() const {
return cursor_shape; return cursor_shape;
} }
void DisplayServerAndroid::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
#if defined(VULKAN_ENABLED)
context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
#endif
}
DisplayServer::VSyncMode DisplayServerAndroid::window_get_vsync_mode(WindowID p_window) const {
#if defined(VULKAN_ENABLED)
return context_vulkan->get_vsync_mode(p_window);
#else
return DisplayServer::VSYNC_ENABLED;
#endif
}

View File

@ -188,6 +188,8 @@ public:
virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID); virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID);
virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const; virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const;
virtual bool can_any_window_draw() const; virtual bool can_any_window_draw() const;
virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID);
virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const;
virtual void alert(const String &p_alert, const String &p_title); virtual void alert(const String &p_alert, const String &p_title);
@ -211,7 +213,7 @@ public:
void mouse_set_mode(MouseMode p_mode); void mouse_set_mode(MouseMode p_mode);
MouseMode mouse_get_mode() const; MouseMode mouse_get_mode() const;
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
static Vector<String> get_rendering_drivers_func(); static Vector<String> get_rendering_drivers_func();
static void register_android_driver(); static void register_android_driver();
@ -221,7 +223,7 @@ public:
virtual Point2i mouse_get_position() const; virtual Point2i mouse_get_position() const;
virtual MouseButton mouse_get_button_state() const; virtual MouseButton mouse_get_button_state() const;
DisplayServerAndroid(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); DisplayServerAndroid(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
~DisplayServerAndroid(); ~DisplayServerAndroid();
}; };

View File

@ -36,7 +36,7 @@ const char *VulkanContextAndroid::_get_platform_surface_extension() const {
return VK_KHR_ANDROID_SURFACE_EXTENSION_NAME; return VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
} }
int VulkanContextAndroid::window_create(ANativeWindow *p_window, int p_width, int p_height) { int VulkanContextAndroid::window_create(ANativeWindow *p_window, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height) {
VkAndroidSurfaceCreateInfoKHR createInfo; VkAndroidSurfaceCreateInfoKHR createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
createInfo.pNext = nullptr; createInfo.pNext = nullptr;
@ -49,7 +49,7 @@ int VulkanContextAndroid::window_create(ANativeWindow *p_window, int p_width, in
ERR_FAIL_V_MSG(-1, "vkCreateAndroidSurfaceKHR failed with error " + itos(err)); ERR_FAIL_V_MSG(-1, "vkCreateAndroidSurfaceKHR failed with error " + itos(err));
} }
return _window_create(DisplayServer::MAIN_WINDOW_ID, surface, p_width, p_height); return _window_create(DisplayServer::MAIN_WINDOW_ID, p_vsync_mode, surface, p_width, p_height);
} }
bool VulkanContextAndroid::_use_validation_layers() { bool VulkanContextAndroid::_use_validation_layers() {

View File

@ -39,7 +39,7 @@ class VulkanContextAndroid : public VulkanContext {
virtual const char *_get_platform_surface_extension() const override; virtual const char *_get_platform_surface_extension() const override;
public: public:
int window_create(ANativeWindow *p_window, int p_width, int p_height); int window_create(ANativeWindow *p_window, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height);
VulkanContextAndroid() = default; VulkanContextAndroid() = default;
~VulkanContextAndroid() override = default; ~VulkanContextAndroid() override = default;

View File

@ -67,7 +67,7 @@ class DisplayServerIPhone : public DisplayServer {
void perform_event(const Ref<InputEvent> &p_event); void perform_event(const Ref<InputEvent> &p_event);
DisplayServerIPhone(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); DisplayServerIPhone(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
~DisplayServerIPhone(); ~DisplayServerIPhone();
public: public:
@ -76,7 +76,7 @@ public:
static DisplayServerIPhone *get_singleton(); static DisplayServerIPhone *get_singleton();
static void register_iphone_driver(); static void register_iphone_driver();
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
static Vector<String> get_rendering_drivers_func(); static Vector<String> get_rendering_drivers_func();
// MARK: - Events // MARK: - Events
@ -176,6 +176,9 @@ public:
virtual bool can_any_window_draw() const override; virtual bool can_any_window_draw() const override;
virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
virtual bool screen_is_touchscreen(int p_screen) const override; virtual bool screen_is_touchscreen(int p_screen) const override;
virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) override; virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) override;

View File

@ -48,7 +48,7 @@ DisplayServerIPhone *DisplayServerIPhone::get_singleton() {
return (DisplayServerIPhone *)DisplayServer::get_singleton(); return (DisplayServerIPhone *)DisplayServer::get_singleton();
} }
DisplayServerIPhone::DisplayServerIPhone(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { DisplayServerIPhone::DisplayServerIPhone(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
rendering_driver = p_rendering_driver; rendering_driver = p_rendering_driver;
#if defined(OPENGL_ENABLED) #if defined(OPENGL_ENABLED)
@ -108,7 +108,7 @@ DisplayServerIPhone::DisplayServerIPhone(const String &p_rendering_driver, Displ
} }
Size2i size = Size2i(layer.bounds.size.width, layer.bounds.size.height) * screen_get_max_scale(); Size2i size = Size2i(layer.bounds.size.width, layer.bounds.size.height) * screen_get_max_scale();
if (context_vulkan->window_create(MAIN_WINDOW_ID, layer, size.width, size.height) != OK) { if (context_vulkan->window_create(MAIN_WINDOW_ID, p_vsync_mode, layer, size.width, size.height) != OK) {
memdelete(context_vulkan); memdelete(context_vulkan);
context_vulkan = nullptr; context_vulkan = nullptr;
ERR_FAIL_MSG("Failed to create Vulkan window."); ERR_FAIL_MSG("Failed to create Vulkan window.");
@ -147,8 +147,8 @@ DisplayServerIPhone::~DisplayServerIPhone() {
#endif #endif
} }
DisplayServer *DisplayServerIPhone::create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { DisplayServer *DisplayServerIPhone::create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
return memnew(DisplayServerIPhone(p_rendering_driver, p_mode, p_flags, p_resolution, r_error)); return memnew(DisplayServerIPhone(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
} }
Vector<String> DisplayServerIPhone::get_rendering_drivers_func() { Vector<String> DisplayServerIPhone::get_rendering_drivers_func() {
@ -581,3 +581,19 @@ void DisplayServerIPhone::resize_window(CGSize viewSize) {
Variant resize_rect = Rect2i(Point2i(), size); Variant resize_rect = Rect2i(Point2i(), size);
_window_callback(window_resize_callback, resize_rect); _window_callback(window_resize_callback, resize_rect);
} }
void DisplayServerIPhone::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
_THREAD_SAFE_METHOD_
#if defined(VULKAN_ENABLED)
context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
#endif
}
DisplayServer::VSyncMode DisplayServerIPhone::window_get_vsync_mode(WindowID p_window) const {
_THREAD_SAFE_METHOD_
#if defined(VULKAN_ENABLED)
return context_vulkan->get_vsync_mode(p_window);
#else
return DisplayServer::VSYNC_ENABLED;
#endif
}

View File

@ -39,7 +39,7 @@ class VulkanContextIPhone : public VulkanContext {
virtual const char *_get_platform_surface_extension() const; virtual const char *_get_platform_surface_extension() const;
public: public:
Error window_create(DisplayServer::WindowID p_window_id, CALayer *p_metal_layer, int p_width, int p_height); Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, CALayer *p_metal_layer, int p_width, int p_height);
VulkanContextIPhone(); VulkanContextIPhone();
~VulkanContextIPhone(); ~VulkanContextIPhone();

View File

@ -35,7 +35,7 @@ const char *VulkanContextIPhone::_get_platform_surface_extension() const {
return VK_MVK_IOS_SURFACE_EXTENSION_NAME; return VK_MVK_IOS_SURFACE_EXTENSION_NAME;
} }
Error VulkanContextIPhone::window_create(DisplayServer::WindowID p_window_id, CALayer *p_metal_layer, int p_width, int p_height) { Error VulkanContextIPhone::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, CALayer *p_metal_layer, int p_width, int p_height) {
VkIOSSurfaceCreateInfoMVK createInfo; VkIOSSurfaceCreateInfoMVK createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK; createInfo.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK;
createInfo.pNext = nullptr; createInfo.pNext = nullptr;
@ -47,7 +47,7 @@ Error VulkanContextIPhone::window_create(DisplayServer::WindowID p_window_id, CA
vkCreateIOSSurfaceMVK(_get_instance(), &createInfo, nullptr, &surface); vkCreateIOSSurfaceMVK(_get_instance(), &createInfo, nullptr, &surface);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE); ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
return _window_create(p_window_id, surface, p_width, p_height); return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height);
} }
VulkanContextIPhone::VulkanContextIPhone() {} VulkanContextIPhone::VulkanContextIPhone() {}

View File

@ -855,10 +855,10 @@ Vector<DisplayServer::WindowID> DisplayServerX11::get_window_list() const {
return ret; return ret;
} }
DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) { DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
WindowID id = _create_window(p_mode, p_flags, p_rect); WindowID id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect);
for (int i = 0; i < WINDOW_FLAG_MAX; i++) { for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) { if (p_flags & (1 << i)) {
window_set_flag(WindowFlags(i), true, id); window_set_flag(WindowFlags(i), true, id);
@ -3641,6 +3641,22 @@ void DisplayServerX11::set_icon(const Ref<Image> &p_icon) {
XSetErrorHandler(oldHandler); XSetErrorHandler(oldHandler);
} }
void DisplayServerX11::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
_THREAD_SAFE_METHOD_
#if defined(VULKAN_ENABLED)
context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
#endif
}
DisplayServer::VSyncMode DisplayServerX11::window_get_vsync_mode(WindowID p_window) const {
_THREAD_SAFE_METHOD_
#if defined(VULKAN_ENABLED)
return context_vulkan->get_vsync_mode(p_window);
#else
return DisplayServer::VSYNC_ENABLED;
#endif
}
Vector<String> DisplayServerX11::get_rendering_drivers_func() { Vector<String> DisplayServerX11::get_rendering_drivers_func() {
Vector<String> drivers; Vector<String> drivers;
@ -3654,8 +3670,8 @@ Vector<String> DisplayServerX11::get_rendering_drivers_func() {
return drivers; return drivers;
} }
DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerX11(p_rendering_driver, p_mode, p_flags, p_resolution, r_error)); DisplayServer *ds = memnew(DisplayServerX11(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
if (r_error != OK) { if (r_error != OK) {
ds->alert("Your video card driver does not support any of the supported Vulkan versions.\n" ds->alert("Your video card driver does not support any of the supported Vulkan versions.\n"
"Please update your drivers or if you have a very old or integrated GPU upgrade it.", "Please update your drivers or if you have a very old or integrated GPU upgrade it.",
@ -3664,7 +3680,7 @@ DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, W
return ds; return ds;
} }
DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) { DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
//Create window //Create window
long visualMask = VisualScreenMask; long visualMask = VisualScreenMask;
@ -3828,7 +3844,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, u
#if defined(VULKAN_ENABLED) #if defined(VULKAN_ENABLED)
if (context_vulkan) { if (context_vulkan) {
Error err = context_vulkan->window_create(id, wd.x11_window, x11_display, p_rect.size.width, p_rect.size.height); Error err = context_vulkan->window_create(id, p_vsync_mode, wd.x11_window, x11_display, p_rect.size.width, p_rect.size.height);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create a Vulkan window"); ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create a Vulkan window");
} }
#endif #endif
@ -3865,7 +3881,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, u
return id; return id;
} }
DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events); Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events);
r_error = OK; r_error = OK;
@ -4101,7 +4117,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
Point2i window_position( Point2i window_position(
(screen_get_size(0).width - p_resolution.width) / 2, (screen_get_size(0).width - p_resolution.width) / 2,
(screen_get_size(0).height - p_resolution.height) / 2); (screen_get_size(0).height - p_resolution.height) / 2);
WindowID main_window = _create_window(p_mode, p_flags, Rect2i(window_position, p_resolution)); WindowID main_window = _create_window(p_mode, p_vsync_mode, p_flags, Rect2i(window_position, p_resolution));
if (main_window == INVALID_WINDOW_ID) { if (main_window == INVALID_WINDOW_ID) {
r_error = ERR_CANT_CREATE; r_error = ERR_CANT_CREATE;
return; return;

View File

@ -152,7 +152,7 @@ class DisplayServerX11 : public DisplayServer {
Map<WindowID, WindowData> windows; Map<WindowID, WindowData> windows;
WindowID window_id_counter = MAIN_WINDOW_ID; WindowID window_id_counter = MAIN_WINDOW_ID;
WindowID _create_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect); WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect);
String internal_clipboard; String internal_clipboard;
Window xdnd_source_window; Window xdnd_source_window;
@ -307,7 +307,7 @@ public:
virtual Vector<DisplayServer::WindowID> get_window_list() const; virtual Vector<DisplayServer::WindowID> get_window_list() const;
virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()); virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i());
virtual void show_window(WindowID p_id); virtual void show_window(WindowID p_id);
virtual void delete_sub_window(WindowID p_id); virtual void delete_sub_window(WindowID p_id);
@ -362,6 +362,9 @@ public:
virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID); virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID);
virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID); virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID);
virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
virtual void cursor_set_shape(CursorShape p_shape); virtual void cursor_set_shape(CursorShape p_shape);
virtual CursorShape cursor_get_shape() const; virtual CursorShape cursor_get_shape() const;
virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot); virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
@ -383,12 +386,12 @@ public:
virtual void set_native_icon(const String &p_filename); virtual void set_native_icon(const String &p_filename);
virtual void set_icon(const Ref<Image> &p_icon); virtual void set_icon(const Ref<Image> &p_icon);
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
static Vector<String> get_rendering_drivers_func(); static Vector<String> get_rendering_drivers_func();
static void register_x11_driver(); static void register_x11_driver();
DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
~DisplayServerX11(); ~DisplayServerX11();
}; };

View File

@ -35,7 +35,7 @@ const char *VulkanContextX11::_get_platform_surface_extension() const {
return VK_KHR_XLIB_SURFACE_EXTENSION_NAME; return VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
} }
Error VulkanContextX11::window_create(DisplayServer::WindowID p_window_id, ::Window p_window, Display *p_display, int p_width, int p_height) { Error VulkanContextX11::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, ::Window p_window, Display *p_display, int p_width, int p_height) {
VkXlibSurfaceCreateInfoKHR createInfo; VkXlibSurfaceCreateInfoKHR createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
createInfo.pNext = nullptr; createInfo.pNext = nullptr;
@ -46,7 +46,7 @@ Error VulkanContextX11::window_create(DisplayServer::WindowID p_window_id, ::Win
VkSurfaceKHR surface; VkSurfaceKHR surface;
VkResult err = vkCreateXlibSurfaceKHR(_get_instance(), &createInfo, nullptr, &surface); VkResult err = vkCreateXlibSurfaceKHR(_get_instance(), &createInfo, nullptr, &surface);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE); ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
return _window_create(p_window_id, surface, p_width, p_height); return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height);
} }
VulkanContextX11::VulkanContextX11() { VulkanContextX11::VulkanContextX11() {

View File

@ -38,7 +38,7 @@ class VulkanContextX11 : public VulkanContext {
virtual const char *_get_platform_surface_extension() const; virtual const char *_get_platform_surface_extension() const;
public: public:
Error window_create(DisplayServer::WindowID p_window_id, ::Window p_window, Display *p_display, int p_width, int p_height); Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, ::Window p_window, Display *p_display, int p_width, int p_height);
VulkanContextX11(); VulkanContextX11();
~VulkanContextX11(); ~VulkanContextX11();

View File

@ -145,7 +145,7 @@ public:
WindowID window_id_counter = MAIN_WINDOW_ID; WindowID window_id_counter = MAIN_WINDOW_ID;
WindowID _create_window(WindowMode p_mode, const Rect2i &p_rect); WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect);
void _update_window(WindowData p_wd); void _update_window(WindowData p_wd);
void _send_window_event(const WindowData &wd, WindowEvent p_event); void _send_window_event(const WindowData &wd, WindowEvent p_event);
static void _dispatch_input_events(const Ref<InputEvent> &p_event); static void _dispatch_input_events(const Ref<InputEvent> &p_event);
@ -232,7 +232,7 @@ public:
virtual Vector<int> get_window_list() const override; virtual Vector<int> get_window_list() const override;
virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override; virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override;
virtual void show_window(WindowID p_id) override; virtual void show_window(WindowID p_id) override;
virtual void delete_sub_window(WindowID p_id) override; virtual void delete_sub_window(WindowID p_id) override;
@ -286,6 +286,9 @@ public:
virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override; virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override;
virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override; virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
virtual Point2i ime_get_selection() const override; virtual Point2i ime_get_selection() const override;
virtual String ime_get_text() const override; virtual String ime_get_text() const override;
@ -314,12 +317,12 @@ public:
virtual void console_set_visible(bool p_enabled) override; virtual void console_set_visible(bool p_enabled) override;
virtual bool is_console_visible() const override; virtual bool is_console_visible() const override;
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
static Vector<String> get_rendering_drivers_func(); static Vector<String> get_rendering_drivers_func();
static void register_osx_driver(); static void register_osx_driver();
DisplayServerOSX(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); DisplayServerOSX(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
~DisplayServerOSX(); ~DisplayServerOSX();
}; };

View File

@ -2388,10 +2388,10 @@ Vector<DisplayServer::WindowID> DisplayServerOSX::get_window_list() const {
return ret; return ret;
} }
DisplayServer::WindowID DisplayServerOSX::create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) { DisplayServer::WindowID DisplayServerOSX::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
WindowID id = _create_window(p_mode, p_rect); WindowID id = _create_window(p_mode, p_vsync_mode, p_rect);
for (int i = 0; i < WINDOW_FLAG_MAX; i++) { for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) { if (p_flags & (1 << i)) {
window_set_flag(WindowFlags(i), true, id); window_set_flag(WindowFlags(i), true, id);
@ -3546,6 +3546,22 @@ void DisplayServerOSX::set_icon(const Ref<Image> &p_icon) {
[nsimg release]; [nsimg release];
} }
void DisplayServerOSX::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
_THREAD_SAFE_METHOD_
#if defined(VULKAN_ENABLED)
context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
#endif
}
DisplayServer::VSyncMode DisplayServerOSX::window_get_vsync_mode(WindowID p_window) const {
_THREAD_SAFE_METHOD_
#if defined(VULKAN_ENABLED)
return context_vulkan->get_vsync_mode(p_window);
#else
return DisplayServer::VSYNC_ENABLED;
#endif
}
Vector<String> DisplayServerOSX::get_rendering_drivers_func() { Vector<String> DisplayServerOSX::get_rendering_drivers_func() {
Vector<String> drivers; Vector<String> drivers;
@ -3596,15 +3612,15 @@ ObjectID DisplayServerOSX::window_get_attached_instance_id(WindowID p_window) co
return windows[p_window].instance_id; return windows[p_window].instance_id;
} }
DisplayServer *DisplayServerOSX::create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { DisplayServer *DisplayServerOSX::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerOSX(p_rendering_driver, p_mode, p_flags, p_resolution, r_error)); DisplayServer *ds = memnew(DisplayServerOSX(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
if (r_error != OK) { if (r_error != OK) {
ds->alert("Your video card driver does not support any of the supported Metal versions.", "Unable to initialize Video driver"); ds->alert("Your video card driver does not support any of the supported Metal versions.", "Unable to initialize Video driver");
} }
return ds; return ds;
} }
DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, const Rect2i &p_rect) { DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect) {
WindowID id; WindowID id;
const float scale = screen_get_max_scale(); const float scale = screen_get_max_scale();
{ {
@ -3651,7 +3667,7 @@ DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, c
#if defined(VULKAN_ENABLED) #if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") { if (rendering_driver == "vulkan") {
if (context_vulkan) { if (context_vulkan) {
Error err = context_vulkan->window_create(window_id_counter, wd.window_view, p_rect.size.width, p_rect.size.height); Error err = context_vulkan->window_create(window_id_counter, p_vsync_mode, wd.window_view, p_rect.size.width, p_rect.size.height);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create a Vulkan context"); ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create a Vulkan context");
} }
} }
@ -3750,7 +3766,7 @@ bool DisplayServerOSX::is_console_visible() const {
return isatty(STDIN_FILENO); return isatty(STDIN_FILENO);
} }
DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events); Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events);
r_error = OK; r_error = OK;
@ -3886,7 +3902,7 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
Point2i window_position( Point2i window_position(
screen_get_position(0).x + (screen_get_size(0).width - p_resolution.width) / 2, screen_get_position(0).x + (screen_get_size(0).width - p_resolution.width) / 2,
screen_get_position(0).y + (screen_get_size(0).height - p_resolution.height) / 2); screen_get_position(0).y + (screen_get_size(0).height - p_resolution.height) / 2);
WindowID main_window = _create_window(p_mode, Rect2i(window_position, p_resolution)); WindowID main_window = _create_window(p_mode, p_vsync_mode, Rect2i(window_position, p_resolution));
ERR_FAIL_COND(main_window == INVALID_WINDOW_ID); ERR_FAIL_COND(main_window == INVALID_WINDOW_ID);
for (int i = 0; i < WINDOW_FLAG_MAX; i++) { for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) { if (p_flags & (1 << i)) {

View File

@ -38,7 +38,7 @@ class VulkanContextOSX : public VulkanContext {
virtual const char *_get_platform_surface_extension() const; virtual const char *_get_platform_surface_extension() const;
public: public:
Error window_create(DisplayServer::WindowID p_window_id, id p_window, int p_width, int p_height); Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, id p_window, int p_width, int p_height);
VulkanContextOSX(); VulkanContextOSX();
~VulkanContextOSX(); ~VulkanContextOSX();

View File

@ -35,7 +35,7 @@ const char *VulkanContextOSX::_get_platform_surface_extension() const {
return VK_MVK_MACOS_SURFACE_EXTENSION_NAME; return VK_MVK_MACOS_SURFACE_EXTENSION_NAME;
} }
Error VulkanContextOSX::window_create(DisplayServer::WindowID p_window_id, id p_window, int p_width, int p_height) { Error VulkanContextOSX::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, id p_window, int p_width, int p_height) {
VkMacOSSurfaceCreateInfoMVK createInfo; VkMacOSSurfaceCreateInfoMVK createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK; createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
createInfo.pNext = nullptr; createInfo.pNext = nullptr;
@ -45,7 +45,7 @@ Error VulkanContextOSX::window_create(DisplayServer::WindowID p_window_id, id p_
VkSurfaceKHR surface; VkSurfaceKHR surface;
VkResult err = vkCreateMacOSSurfaceMVK(_get_instance(), &createInfo, nullptr, &surface); VkResult err = vkCreateMacOSSurfaceMVK(_get_instance(), &createInfo, nullptr, &surface);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE); ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
return _window_create(p_window_id, surface, p_width, p_height); return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height);
} }
VulkanContextOSX::VulkanContextOSX() { VulkanContextOSX::VulkanContextOSX() {

View File

@ -66,46 +66,13 @@ int ContextGL_Windows::get_window_height() {
return OS::get_singleton()->get_video_mode().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() { void ContextGL_Windows::swap_buffers() {
SwapBuffers(hDC); SwapBuffers(hDC);
if (use_vsync) {
bool vsync_via_compositor_now = should_vsync_via_compositor();
if (vsync_via_compositor_now && wglGetSwapIntervalEXT() == 0) {
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) { void ContextGL_Windows::set_use_vsync(bool p_use) {
vsync_via_compositor = p_use && should_vsync_via_compositor();
if (wglSwapIntervalEXT) { if (wglSwapIntervalEXT) {
int swap_interval = (p_use && !vsync_via_compositor) ? 1 : 0; int swap_interval = p_use ? 1 : 0;
wglSwapIntervalEXT(swap_interval); wglSwapIntervalEXT(swap_interval);
} }
@ -210,7 +177,6 @@ ContextGL_Windows::ContextGL_Windows(HWND hwnd, bool p_opengl_3_context) {
opengl_3_context = p_opengl_3_context; opengl_3_context = p_opengl_3_context;
hWnd = hwnd; hWnd = hwnd;
use_vsync = false; use_vsync = false;
vsync_via_compositor = false;
pixel_format = 0; pixel_format = 0;
} }

View File

@ -50,13 +50,10 @@ class ContextGL_Windows {
HWND hWnd; HWND hWnd;
bool opengl_3_context; bool opengl_3_context;
bool use_vsync; bool use_vsync;
bool vsync_via_compositor;
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT; PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT; PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT;
static bool should_vsync_via_compositor();
public: public:
void release_current(); void release_current();

View File

@ -477,10 +477,10 @@ DisplayServer::WindowID DisplayServerWindows::get_window_at_screen_position(cons
return INVALID_WINDOW_ID; return INVALID_WINDOW_ID;
} }
DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) { DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
WindowID window_id = _create_window(p_mode, p_flags, p_rect); WindowID window_id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect);
ERR_FAIL_COND_V_MSG(window_id == INVALID_WINDOW_ID, INVALID_WINDOW_ID, "Failed to create sub window."); ERR_FAIL_COND_V_MSG(window_id == INVALID_WINDOW_ID, INVALID_WINDOW_ID, "Failed to create sub window.");
WindowData &wd = windows[window_id]; WindowData &wd = windows[window_id];
@ -1697,11 +1697,20 @@ void DisplayServerWindows::set_icon(const Ref<Image> &p_icon) {
SendMessage(windows[MAIN_WINDOW_ID].hWnd, WM_SETICON, ICON_BIG, (LPARAM)hicon); SendMessage(windows[MAIN_WINDOW_ID].hWnd, WM_SETICON, ICON_BIG, (LPARAM)hicon);
} }
void DisplayServerWindows::vsync_set_use_via_compositor(bool p_enable) { void DisplayServerWindows::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
_THREAD_SAFE_METHOD_
#if defined(VULKAN_ENABLED)
context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
#endif
} }
bool DisplayServerWindows::vsync_is_using_via_compositor() const { DisplayServer::VSyncMode DisplayServerWindows::window_get_vsync_mode(WindowID p_window) const {
return false; _THREAD_SAFE_METHOD_
#if defined(VULKAN_ENABLED)
return context_vulkan->get_vsync_mode(p_window);
#else
return DisplayServer::VSYNC_ENABLED;
#endif
} }
void DisplayServerWindows::set_context(Context p_context) { void DisplayServerWindows::set_context(Context p_context) {
@ -2968,7 +2977,7 @@ void DisplayServerWindows::_update_tablet_ctx(const String &p_old_driver, const
} }
} }
DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) { DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
DWORD dwExStyle; DWORD dwExStyle;
DWORD dwStyle; DWORD dwStyle;
@ -3030,7 +3039,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
#ifdef VULKAN_ENABLED #ifdef VULKAN_ENABLED
if (rendering_driver == "vulkan") { if (rendering_driver == "vulkan") {
if (context_vulkan->window_create(id, wd.hWnd, hInstance, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top) == -1) { if (context_vulkan->window_create(id, p_vsync_mode, wd.hWnd, hInstance, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top) == -1) {
memdelete(context_vulkan); memdelete(context_vulkan);
context_vulkan = nullptr; context_vulkan = nullptr;
windows.erase(id); windows.erase(id);
@ -3151,7 +3160,7 @@ void DisplayServerWindows::tablet_set_current_driver(const String &p_driver) {
} }
} }
DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
drop_events = false; drop_events = false;
key_event_pos = 0; key_event_pos = 0;
@ -3270,7 +3279,6 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
} }
context_gles2->set_use_vsync(video_mode.use_vsync); context_gles2->set_use_vsync(video_mode.use_vsync);
set_vsync_via_compositor(video_mode.vsync_via_compositor);
if (RasterizerGLES2::is_viable() == OK) { if (RasterizerGLES2::is_viable() == OK) {
RasterizerGLES2::register_config(); RasterizerGLES2::register_config();
@ -3286,7 +3294,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
(screen_get_size(0).width - p_resolution.width) / 2, (screen_get_size(0).width - p_resolution.width) / 2,
(screen_get_size(0).height - p_resolution.height) / 2); (screen_get_size(0).height - p_resolution.height) / 2);
WindowID main_window = _create_window(p_mode, 0, Rect2i(window_position, p_resolution)); WindowID main_window = _create_window(p_mode, p_vsync_mode, 0, Rect2i(window_position, p_resolution));
ERR_FAIL_COND_MSG(main_window == INVALID_WINDOW_ID, "Failed to create main window."); ERR_FAIL_COND_MSG(main_window == INVALID_WINDOW_ID, "Failed to create main window.");
for (int i = 0; i < WINDOW_FLAG_MAX; i++) { for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
@ -3347,8 +3355,8 @@ Vector<String> DisplayServerWindows::get_rendering_drivers_func() {
return drivers; return drivers;
} }
DisplayServer *DisplayServerWindows::create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { DisplayServer *DisplayServerWindows::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerWindows(p_rendering_driver, p_mode, p_flags, p_resolution, r_error)); DisplayServer *ds = memnew(DisplayServerWindows(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
if (r_error != OK) { if (r_error != OK) {
ds->alert("Your video card driver does not support any of the supported Vulkan versions.\n" ds->alert("Your video card driver does not support any of the supported Vulkan versions.\n"
"Please update your drivers or if you have a very old or integrated GPU upgrade it.", "Please update your drivers or if you have a very old or integrated GPU upgrade it.",

View File

@ -389,7 +389,7 @@ class DisplayServerWindows : public DisplayServer {
JoypadWindows *joypad; JoypadWindows *joypad;
WindowID _create_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect); WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect);
WindowID window_id_counter = MAIN_WINDOW_ID; WindowID window_id_counter = MAIN_WINDOW_ID;
Map<WindowID, WindowData> windows; Map<WindowID, WindowData> windows;
@ -469,7 +469,7 @@ public:
virtual Vector<DisplayServer::WindowID> get_window_list() const; virtual Vector<DisplayServer::WindowID> get_window_list() const;
virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()); virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i());
virtual void show_window(WindowID p_window); virtual void show_window(WindowID p_window);
virtual void delete_sub_window(WindowID p_window); virtual void delete_sub_window(WindowID p_window);
@ -525,6 +525,9 @@ public:
virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID); virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID);
virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID); virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID);
virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
virtual void console_set_visible(bool p_enabled); virtual void console_set_visible(bool p_enabled);
virtual bool is_console_visible() const; virtual bool is_console_visible() const;
@ -558,16 +561,13 @@ public:
virtual void set_native_icon(const String &p_filename); virtual void set_native_icon(const String &p_filename);
virtual void set_icon(const Ref<Image> &p_icon); virtual void set_icon(const Ref<Image> &p_icon);
virtual void vsync_set_use_via_compositor(bool p_enable);
virtual bool vsync_is_using_via_compositor() const;
virtual void set_context(Context p_context); virtual void set_context(Context p_context);
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
static Vector<String> get_rendering_drivers_func(); static Vector<String> get_rendering_drivers_func();
static void register_windows_driver(); static void register_windows_driver();
DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
~DisplayServerWindows(); ~DisplayServerWindows();
}; };

View File

@ -35,18 +35,17 @@ const char *VulkanContextWindows::_get_platform_surface_extension() const {
return VK_KHR_WIN32_SURFACE_EXTENSION_NAME; return VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
} }
int VulkanContextWindows::window_create(DisplayServer::WindowID p_window_id, HWND p_window, HINSTANCE p_instance, int p_width, int p_height) { int VulkanContextWindows::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, HWND p_window, HINSTANCE p_instance, int p_width, int p_height) {
VkWin32SurfaceCreateInfoKHR createInfo; VkWin32SurfaceCreateInfoKHR createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
createInfo.pNext = nullptr; createInfo.pNext = nullptr;
createInfo.flags = 0; createInfo.flags = 0;
createInfo.hinstance = p_instance; createInfo.hinstance = p_instance;
createInfo.hwnd = p_window; createInfo.hwnd = p_window;
VkSurfaceKHR surface; VkSurfaceKHR surface;
VkResult err = vkCreateWin32SurfaceKHR(_get_instance(), &createInfo, nullptr, &surface); VkResult err = vkCreateWin32SurfaceKHR(_get_instance(), &createInfo, nullptr, &surface);
ERR_FAIL_COND_V(err, -1); ERR_FAIL_COND_V(err, -1);
return _window_create(p_window_id, surface, p_width, p_height); return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height);
} }
VulkanContextWindows::VulkanContextWindows() { VulkanContextWindows::VulkanContextWindows() {

View File

@ -38,7 +38,7 @@ class VulkanContextWindows : public VulkanContext {
virtual const char *_get_platform_surface_extension() const; virtual const char *_get_platform_surface_extension() const;
public: public:
int window_create(DisplayServer::WindowID p_window_id, HWND p_window, HINSTANCE p_instance, int p_width, int p_height); int window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, HWND p_window, HINSTANCE p_instance, int p_width, int p_height);
VulkanContextWindows(); VulkanContextWindows();
~VulkanContextWindows(); ~VulkanContextWindows();

View File

@ -227,7 +227,8 @@ void Window::_make_window() {
} }
} }
window_id = DisplayServer::get_singleton()->create_sub_window(DisplayServer::WindowMode(mode), f, Rect2i(position, size)); DisplayServer::VSyncMode vsync_mode = DisplayServer::get_singleton()->window_get_vsync_mode(DisplayServer::MAIN_WINDOW_ID);
window_id = DisplayServer::get_singleton()->create_sub_window(DisplayServer::WindowMode(mode), vsync_mode, f, Rect2i(position, size));
ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID); ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID);
DisplayServer::get_singleton()->window_set_current_screen(current_screen, window_id); DisplayServer::get_singleton()->window_set_current_screen(current_screen, window_id);
DisplayServer::get_singleton()->window_set_max_size(max_size, window_id); DisplayServer::get_singleton()->window_set_max_size(max_size, window_id);

View File

@ -35,7 +35,6 @@
#include "servers/display_server_headless.h" #include "servers/display_server_headless.h"
DisplayServer *DisplayServer::singleton = nullptr; DisplayServer *DisplayServer::singleton = nullptr;
DisplayServer::SwitchVSyncCallbackInThread DisplayServer::switch_vsync_function = nullptr;
bool DisplayServer::hidpi_allowed = false; bool DisplayServer::hidpi_allowed = false;
@ -185,7 +184,7 @@ bool DisplayServer::screen_is_kept_on() const {
return false; return false;
} }
DisplayServer::WindowID DisplayServer::create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) { DisplayServer::WindowID DisplayServer::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Sub-windows not supported by this display server."); ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Sub-windows not supported by this display server.");
} }
@ -309,29 +308,13 @@ void DisplayServer::set_icon(const Ref<Image> &p_icon) {
WARN_PRINT("Icon not supported by this display server."); WARN_PRINT("Icon not supported by this display server.");
} }
void DisplayServer::_set_use_vsync(bool p_enable) { void DisplayServer::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
WARN_PRINT("VSync not supported by this display server."); WARN_PRINT("Changing the VSync mode is not supported by this display server.");
} }
void DisplayServer::vsync_set_enabled(bool p_enable) { DisplayServer::VSyncMode DisplayServer::window_get_vsync_mode(WindowID p_window) const {
vsync_enabled = p_enable; WARN_PRINT("Changing the VSync mode is not supported by this display server.");
if (switch_vsync_function) { //if a function was set, use function return VSyncMode::VSYNC_ENABLED;
switch_vsync_function(p_enable);
} else { //otherwise just call here
_set_use_vsync(p_enable);
}
}
bool DisplayServer::vsync_is_enabled() const {
return vsync_enabled;
}
void DisplayServer::vsync_set_use_via_compositor(bool p_enable) {
WARN_PRINT("VSync via compositor not supported by this display server.");
}
bool DisplayServer::vsync_is_using_via_compositor() const {
return false;
} }
void DisplayServer::set_context(Context p_context) { void DisplayServer::set_context(Context p_context) {
@ -394,7 +377,7 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_window_list"), &DisplayServer::get_window_list); ClassDB::bind_method(D_METHOD("get_window_list"), &DisplayServer::get_window_list);
ClassDB::bind_method(D_METHOD("get_window_at_screen_position", "position"), &DisplayServer::get_window_at_screen_position); ClassDB::bind_method(D_METHOD("get_window_at_screen_position", "position"), &DisplayServer::get_window_at_screen_position);
ClassDB::bind_method(D_METHOD("create_sub_window", "mode", "flags", "rect"), &DisplayServer::create_sub_window, DEFVAL(Rect2i())); ClassDB::bind_method(D_METHOD("create_sub_window", "mode", "vsync_mode", "flags", "rect"), &DisplayServer::create_sub_window, DEFVAL(Rect2i()));
ClassDB::bind_method(D_METHOD("delete_sub_window", "window_id"), &DisplayServer::delete_sub_window); ClassDB::bind_method(D_METHOD("delete_sub_window", "window_id"), &DisplayServer::delete_sub_window);
ClassDB::bind_method(D_METHOD("window_set_title", "title", "window_id"), &DisplayServer::window_set_title, DEFVAL(MAIN_WINDOW_ID)); ClassDB::bind_method(D_METHOD("window_set_title", "title", "window_id"), &DisplayServer::window_set_title, DEFVAL(MAIN_WINDOW_ID));
@ -441,6 +424,9 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("window_set_ime_active", "active", "window_id"), &DisplayServer::window_set_ime_active, DEFVAL(MAIN_WINDOW_ID)); ClassDB::bind_method(D_METHOD("window_set_ime_active", "active", "window_id"), &DisplayServer::window_set_ime_active, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_set_ime_position", "position", "window_id"), &DisplayServer::window_set_ime_position, DEFVAL(MAIN_WINDOW_ID)); ClassDB::bind_method(D_METHOD("window_set_ime_position", "position", "window_id"), &DisplayServer::window_set_ime_position, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_set_vsync_mode", "vsync_mode", "window_id"), &DisplayServer::window_set_vsync_mode, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_get_vsync_mode", "window_id"), &DisplayServer::window_get_vsync_mode, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("ime_get_selection"), &DisplayServer::ime_get_selection); ClassDB::bind_method(D_METHOD("ime_get_selection"), &DisplayServer::ime_get_selection);
ClassDB::bind_method(D_METHOD("ime_get_text"), &DisplayServer::ime_get_text); ClassDB::bind_method(D_METHOD("ime_get_text"), &DisplayServer::ime_get_text);
@ -472,12 +458,6 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("process_events"), &DisplayServer::process_events); ClassDB::bind_method(D_METHOD("process_events"), &DisplayServer::process_events);
ClassDB::bind_method(D_METHOD("force_process_and_drop_events"), &DisplayServer::force_process_and_drop_events); ClassDB::bind_method(D_METHOD("force_process_and_drop_events"), &DisplayServer::force_process_and_drop_events);
ClassDB::bind_method(D_METHOD("vsync_set_enabled", "enabled"), &DisplayServer::vsync_set_enabled);
ClassDB::bind_method(D_METHOD("vsync_is_enabled"), &DisplayServer::vsync_is_enabled);
ClassDB::bind_method(D_METHOD("vsync_set_use_via_compositor", "enabled"), &DisplayServer::vsync_set_use_via_compositor);
ClassDB::bind_method(D_METHOD("vsync_is_using_via_compositor"), &DisplayServer::vsync_is_using_via_compositor);
ClassDB::bind_method(D_METHOD("set_native_icon", "filename"), &DisplayServer::set_native_icon); ClassDB::bind_method(D_METHOD("set_native_icon", "filename"), &DisplayServer::set_native_icon);
ClassDB::bind_method(D_METHOD("set_icon", "image"), &DisplayServer::set_icon); ClassDB::bind_method(D_METHOD("set_icon", "image"), &DisplayServer::set_icon);
@ -561,6 +541,11 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(WINDOW_EVENT_CLOSE_REQUEST); BIND_ENUM_CONSTANT(WINDOW_EVENT_CLOSE_REQUEST);
BIND_ENUM_CONSTANT(WINDOW_EVENT_GO_BACK_REQUEST); BIND_ENUM_CONSTANT(WINDOW_EVENT_GO_BACK_REQUEST);
BIND_ENUM_CONSTANT(WINDOW_EVENT_DPI_CHANGE); BIND_ENUM_CONSTANT(WINDOW_EVENT_DPI_CHANGE);
BIND_ENUM_CONSTANT(VSYNC_DISABLED);
BIND_ENUM_CONSTANT(VSYNC_ENABLED);
BIND_ENUM_CONSTANT(VSYNC_ADAPTIVE);
BIND_ENUM_CONSTANT(VSYNC_MAILBOX);
} }
void DisplayServer::register_create_function(const char *p_name, CreateFunction p_function, GetRenderingDriversFunction p_get_drivers) { void DisplayServer::register_create_function(const char *p_name, CreateFunction p_function, GetRenderingDriversFunction p_get_drivers) {
@ -587,9 +572,9 @@ Vector<String> DisplayServer::get_create_function_rendering_drivers(int p_index)
return server_create_functions[p_index].get_rendering_drivers_function(); return server_create_functions[p_index].get_rendering_drivers_function();
} }
DisplayServer *DisplayServer::create(int p_index, const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { DisplayServer *DisplayServer::create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
ERR_FAIL_INDEX_V(p_index, server_create_count, nullptr); ERR_FAIL_INDEX_V(p_index, server_create_count, nullptr);
return server_create_functions[p_index].create_function(p_rendering_driver, p_mode, p_flags, p_resolution, r_error); return server_create_functions[p_index].create_function(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error);
} }
void DisplayServer::_input_set_mouse_mode(Input::MouseMode p_mode) { void DisplayServer::_input_set_mouse_mode(Input::MouseMode p_mode) {

View File

@ -42,7 +42,6 @@ class DisplayServer : public Object {
GDCLASS(DisplayServer, Object) GDCLASS(DisplayServer, Object)
static DisplayServer *singleton; static DisplayServer *singleton;
bool vsync_enabled = true;
static bool hidpi_allowed; static bool hidpi_allowed;
public: public:
@ -57,7 +56,14 @@ public:
WINDOW_MODE_FULLSCREEN WINDOW_MODE_FULLSCREEN
}; };
typedef DisplayServer *(*CreateFunction)(const String &, WindowMode, uint32_t, const Size2i &, Error &r_error); enum VSyncMode {
VSYNC_DISABLED,
VSYNC_ENABLED,
VSYNC_ADAPTIVE,
VSYNC_MAILBOX
};
typedef DisplayServer *(*CreateFunction)(const String &, WindowMode, VSyncMode, uint32_t, const Size2i &, Error &r_error);
typedef Vector<String> (*GetRenderingDriversFunction)(); typedef Vector<String> (*GetRenderingDriversFunction)();
private: private:
@ -84,7 +90,6 @@ protected:
static int server_create_count; static int server_create_count;
friend class RendererViewport; friend class RendererViewport;
virtual void _set_use_vsync(bool p_enable);
public: public:
enum Feature { enum Feature {
@ -221,7 +226,7 @@ public:
WINDOW_FLAG_NO_FOCUS_BIT = (1 << WINDOW_FLAG_NO_FOCUS) WINDOW_FLAG_NO_FOCUS_BIT = (1 << WINDOW_FLAG_NO_FOCUS)
}; };
virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()); virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i());
virtual void show_window(WindowID p_id); virtual void show_window(WindowID p_id);
virtual void delete_sub_window(WindowID p_id); virtual void delete_sub_window(WindowID p_id);
@ -272,6 +277,9 @@ public:
virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) = 0; virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) = 0;
virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const = 0; virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const = 0;
virtual void window_set_vsync_mode(VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID);
virtual VSyncMode window_get_vsync_mode(WindowID p_window) const;
virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const = 0; virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const = 0;
virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) = 0; virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) = 0;
@ -352,18 +360,6 @@ public:
virtual void set_native_icon(const String &p_filename); virtual void set_native_icon(const String &p_filename);
virtual void set_icon(const Ref<Image> &p_icon); virtual void set_icon(const Ref<Image> &p_icon);
typedef void (*SwitchVSyncCallbackInThread)(bool);
static SwitchVSyncCallbackInThread switch_vsync_function;
void vsync_set_enabled(bool p_enable);
bool vsync_is_enabled() const;
virtual void vsync_set_use_via_compositor(bool p_enable);
virtual bool vsync_is_using_via_compositor() const;
//real, actual overridable function to switch vsync, which needs to be called from graphics thread if needed
enum Context { enum Context {
CONTEXT_EDITOR, CONTEXT_EDITOR,
CONTEXT_PROJECTMAN, CONTEXT_PROJECTMAN,
@ -376,7 +372,7 @@ public:
static int get_create_function_count(); static int get_create_function_count();
static const char *get_create_function_name(int p_index); static const char *get_create_function_name(int p_index);
static Vector<String> get_create_function_rendering_drivers(int p_index); static Vector<String> get_create_function_rendering_drivers(int p_index);
static DisplayServer *create(int p_index, const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); static DisplayServer *create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
DisplayServer(); DisplayServer();
~DisplayServer(); ~DisplayServer();
@ -389,5 +385,6 @@ VARIANT_ENUM_CAST(DisplayServer::ScreenOrientation)
VARIANT_ENUM_CAST(DisplayServer::WindowMode) VARIANT_ENUM_CAST(DisplayServer::WindowMode)
VARIANT_ENUM_CAST(DisplayServer::WindowFlags) VARIANT_ENUM_CAST(DisplayServer::WindowFlags)
VARIANT_ENUM_CAST(DisplayServer::CursorShape) VARIANT_ENUM_CAST(DisplayServer::CursorShape)
VARIANT_ENUM_CAST(DisplayServer::VSyncMode)
#endif // DISPLAY_SERVER_H #endif // DISPLAY_SERVER_H

View File

@ -45,7 +45,7 @@ private:
return drivers; return drivers;
} }
static DisplayServer *create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { static DisplayServer *create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
r_error = OK; r_error = OK;
RasterizerDummy::make_current(); RasterizerDummy::make_current();
return memnew(DisplayServerHeadless()); return memnew(DisplayServerHeadless());

View File

@ -1116,9 +1116,9 @@ void RendererViewport::set_default_clear_color(const Color &p_color) {
RSG::storage->set_default_clear_color(p_color); RSG::storage->set_default_clear_color(p_color);
} }
//workaround for setting this on thread // Workaround for setting this on thread.
void RendererViewport::call_set_use_vsync(bool p_enable) { void RendererViewport::call_set_vsync_mode(DisplayServer::VSyncMode p_mode, DisplayServer::WindowID p_window) {
DisplayServer::get_singleton()->_set_use_vsync(p_enable); DisplayServer::get_singleton()->window_set_vsync_mode(p_mode, p_window);
} }
int RendererViewport::get_total_objects_drawn() const { int RendererViewport::get_total_objects_drawn() const {

View File

@ -271,8 +271,8 @@ public:
int get_total_vertices_drawn() const; int get_total_vertices_drawn() const;
int get_total_draw_calls_used() const; int get_total_draw_calls_used() const;
//workaround for setting this on thread // Workaround for setting this on thread.
void call_set_use_vsync(bool p_enable); void call_set_vsync_mode(DisplayServer::VSyncMode p_mode, DisplayServer::WindowID p_window);
RendererViewport(); RendererViewport();
virtual ~RendererViewport() {} virtual ~RendererViewport() {}

View File

@ -577,7 +577,7 @@ public:
FUNC1RC(float, viewport_get_measured_render_time_cpu, RID) FUNC1RC(float, viewport_get_measured_render_time_cpu, RID)
FUNC1RC(float, viewport_get_measured_render_time_gpu, RID) FUNC1RC(float, viewport_get_measured_render_time_gpu, RID)
FUNC1(call_set_use_vsync, bool) FUNC2(call_set_vsync_mode, DisplayServer::VSyncMode, DisplayServer::WindowID)
/* ENVIRONMENT API */ /* ENVIRONMENT API */

View File

@ -1454,7 +1454,7 @@ public:
virtual void set_debug_generate_wireframes(bool p_generate) = 0; virtual void set_debug_generate_wireframes(bool p_generate) = 0;
virtual void call_set_use_vsync(bool p_enable) = 0; virtual void call_set_vsync_mode(DisplayServer::VSyncMode p_mode, DisplayServer::WindowID p_window) = 0;
virtual bool is_low_end() const = 0; virtual bool is_low_end() const = 0;