diff --git a/core/os/os.h b/core/os/os.h
index 91e0ce937944..22197d3517a4 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -111,9 +111,6 @@ class OS {
virtual void initialize() = 0;
virtual void initialize_joypads() = 0;
- void set_current_rendering_driver_name(const String &p_driver_name) { _current_rendering_driver_name = p_driver_name; }
- void set_current_rendering_method(const String &p_name) { _current_rendering_method = p_name; }
-
void set_display_driver_id(int p_display_driver_id) { _display_driver_id = p_display_driver_id; }
virtual void set_main_loop(MainLoop *p_main_loop) = 0;
@@ -131,6 +128,9 @@ class OS {
static OS *get_singleton();
+ void set_current_rendering_driver_name(const String &p_driver_name) { _current_rendering_driver_name = p_driver_name; }
+ void set_current_rendering_method(const String &p_name) { _current_rendering_method = p_name; }
+
String get_current_rendering_driver_name() const { return _current_rendering_driver_name; }
String get_current_rendering_method() const { return _current_rendering_method; }
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index d78fca5e16cd..aceafa2a16d6 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -2526,8 +2526,8 @@
[b]Note:[/b] This setting is implemented only on Linux/X11.
- If [code]true[/code], the compatibility renderer will fall back to native OpenGL if ANGLE over Metal is not supported.
- [b]Note:[/b] This setting is implemented only on macOS.
+ If [code]true[/code], the compatibility renderer will fall back to native OpenGL if ANGLE is not supported, or ANGLE dynamic libraries aren't found.
+ [b]Note:[/b] This setting is implemented on macOS and Windows.
An [Array] of devices which should always use the ANGLE renderer.
@@ -2790,6 +2790,10 @@
If [code]true[/code], the forward renderer will fall back to Direct3D 12 if Vulkan is not supported.
[b]Note:[/b] This setting is implemented only on Windows.
+
+ If [code]true[/code], the forward renderer will fall back to OpenGL 3 if both Direct3D 12, Metal and Vulkan are not supported.
+ [b]Note:[/b] This setting is implemented only on Windows, Android, macOS, iOS, and Linux/X11.
+
If [code]true[/code], the forward renderer will fall back to Vulkan if Direct3D 12 is not supported.
[b]Note:[/b] This setting is implemented only on Windows.
diff --git a/drivers/d3d12/SCsub b/drivers/d3d12/SCsub
index 55ba1dc579c5..f1264f040d3d 100644
--- a/drivers/d3d12/SCsub
+++ b/drivers/d3d12/SCsub
@@ -138,7 +138,6 @@ if env.msvc:
]
else:
extra_defines += [
- ("__REQUIRED_RPCNDR_H_VERSION__", 475),
"HAVE_STRUCT_TIMESPEC",
]
diff --git a/drivers/d3d12/rendering_device_driver_d3d12.h b/drivers/d3d12/rendering_device_driver_d3d12.h
index 61b1498755f6..fb7fbdc02d79 100644
--- a/drivers/d3d12/rendering_device_driver_d3d12.h
+++ b/drivers/d3d12/rendering_device_driver_d3d12.h
@@ -36,6 +36,11 @@
#include "core/templates/self_list.h"
#include "servers/rendering/rendering_device_driver.h"
+#ifndef _MSC_VER
+// Match current version used by MinGW, MSVC and Direct3D 12 headers use 500.
+#define __REQUIRED_RPCNDR_H_VERSION__ 475
+#endif
+
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
diff --git a/drivers/egl/egl_manager.cpp b/drivers/egl/egl_manager.cpp
index 9c1d08331d25..4477ba7752cb 100644
--- a/drivers/egl/egl_manager.cpp
+++ b/drivers/egl/egl_manager.cpp
@@ -357,7 +357,7 @@ Error EGLManager::initialize(void *p_native_display) {
// have to temporarily get a proper display and reload EGL once again to
// initialize everything else.
if (!gladLoaderLoadEGL(EGL_NO_DISPLAY)) {
- ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Can't load EGL.");
+ ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Can't load EGL dynamic library.");
}
EGLDisplay tmp_display = EGL_NO_DISPLAY;
@@ -387,7 +387,7 @@ Error EGLManager::initialize(void *p_native_display) {
int version = gladLoaderLoadEGL(tmp_display);
if (!version) {
eglTerminate(tmp_display);
- ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Can't load EGL.");
+ ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Can't load EGL dynamic library.");
}
int major = GLAD_VERSION_MAJOR(version);
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index fa7f409ce2cf..db9555e24a53 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -172,6 +172,10 @@
#include "modules/modules_enabled.gen.h" // For gdscript, mono.
+#if defined(GLES3_ENABLED)
+#include "drivers/gles3/rasterizer_gles3.h"
+#endif
+
EditorNode *EditorNode::singleton = nullptr;
static const String EDITOR_NODE_CONFIG_SECTION = "EditorNode";
@@ -5018,8 +5022,8 @@ String EditorNode::_get_system_info() const {
#ifdef LINUXBSD_ENABLED
const String display_server = OS::get_singleton()->get_environment("XDG_SESSION_TYPE").capitalize().replace(" ", ""); // `replace` is necessary, because `capitalize` introduces a whitespace between "x" and "11".
#endif // LINUXBSD_ENABLED
- String driver_name = GLOBAL_GET("rendering/rendering_device/driver");
- String rendering_method = GLOBAL_GET("rendering/renderer/rendering_method");
+ String driver_name = OS::get_singleton()->get_current_rendering_driver_name().to_lower();
+ String rendering_method = OS::get_singleton()->get_current_rendering_method().to_lower();
const String rendering_device_name = RenderingServer::get_singleton()->get_video_adapter_name();
@@ -5055,12 +5059,23 @@ String EditorNode::_get_system_info() const {
rendering_method = "Mobile";
} else if (rendering_method == "gl_compatibility") {
rendering_method = "Compatibility";
- driver_name = GLOBAL_GET("rendering/gl_compatibility/driver");
}
if (driver_name == "vulkan") {
driver_name = "Vulkan";
- } else if (driver_name.begins_with("opengl3")) {
- driver_name = "GLES3";
+ } else if (driver_name == "d3d12") {
+ driver_name = "Direct3D 12";
+#if defined(GLES3_ENABLED)
+ } else if (driver_name == "opengl3_angle") {
+ driver_name = "OpenGL ES 3/ANGLE";
+ } else if (driver_name == "opengl3_es") {
+ driver_name = "OpenGL ES 3";
+ } else if (driver_name == "opengl3") {
+ if (RasterizerGLES3::is_gles_over_gl()) {
+ driver_name = "OpenGL 3";
+ } else {
+ driver_name = "OpenGL ES 3";
+ }
+#endif
}
// Join info.
diff --git a/editor/project_manager/project_dialog.cpp b/editor/project_manager/project_dialog.cpp
index ce7389b3ea4f..b1791c66ab64 100644
--- a/editor/project_manager/project_dialog.cpp
+++ b/editor/project_manager/project_dialog.cpp
@@ -444,6 +444,8 @@ void ProjectDialog::_renderer_selected() {
String renderer_type = renderer_button_group->get_pressed_button()->get_meta(SNAME("rendering_method"));
+ bool rd_error = false;
+
if (renderer_type == "forward_plus") {
renderer_info->set_text(
String::utf8("• ") + TTR("Supports desktop platforms only.") +
@@ -451,6 +453,7 @@ void ProjectDialog::_renderer_selected() {
String::utf8("\n• ") + TTR("Can scale to large complex scenes.") +
String::utf8("\n• ") + TTR("Uses RenderingDevice backend.") +
String::utf8("\n• ") + TTR("Slower rendering of simple scenes."));
+ rd_error = !rendering_device_supported;
} else if (renderer_type == "mobile") {
renderer_info->set_text(
String::utf8("• ") + TTR("Supports desktop + mobile platforms.") +
@@ -458,16 +461,24 @@ void ProjectDialog::_renderer_selected() {
String::utf8("\n• ") + TTR("Less scalable for complex scenes.") +
String::utf8("\n• ") + TTR("Uses RenderingDevice backend.") +
String::utf8("\n• ") + TTR("Fast rendering of simple scenes."));
+ rd_error = !rendering_device_supported;
} else if (renderer_type == "gl_compatibility") {
renderer_info->set_text(
String::utf8("• ") + TTR("Supports desktop, mobile + web platforms.") +
- String::utf8("\n• ") + TTR("Least advanced 3D graphics (currently work-in-progress).") +
+ String::utf8("\n• ") + TTR("Least advanced 3D graphics.") +
String::utf8("\n• ") + TTR("Intended for low-end/older devices.") +
String::utf8("\n• ") + TTR("Uses OpenGL 3 backend (OpenGL 3.3/ES 3.0/WebGL2).") +
String::utf8("\n• ") + TTR("Fastest rendering of simple scenes."));
} else {
WARN_PRINT("Unknown renderer type. Please report this as a bug on GitHub.");
}
+
+ rd_not_supported->set_visible(rd_error);
+ get_ok_button()->set_disabled(rd_error);
+ if (rd_error) {
+ // Needs to be set here since theme colors aren't available at startup.
+ rd_not_supported->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("error_color"), EditorStringName(Editor)));
+ }
}
void ProjectDialog::_nonempty_confirmation_ok_pressed() {
@@ -922,10 +933,16 @@ ProjectDialog::ProjectDialog() {
default_renderer_type = EditorSettings::get_singleton()->get_setting("project_manager/default_renderer");
}
+ rendering_device_supported = DisplayServer::can_create_rendering_device();
+
+ if (!rendering_device_supported) {
+ default_renderer_type = "gl_compatibility";
+ }
+
Button *rs_button = memnew(CheckBox);
rs_button->set_button_group(renderer_button_group);
rs_button->set_text(TTR("Forward+"));
-#if defined(WEB_ENABLED)
+#ifndef RD_ENABLED
rs_button->set_disabled(true);
#endif
rs_button->set_meta(SNAME("rendering_method"), "forward_plus");
@@ -937,7 +954,7 @@ ProjectDialog::ProjectDialog() {
rs_button = memnew(CheckBox);
rs_button->set_button_group(renderer_button_group);
rs_button->set_text(TTR("Mobile"));
-#if defined(WEB_ENABLED)
+#ifndef RD_ENABLED
rs_button->set_disabled(true);
#endif
rs_button->set_meta(SNAME("rendering_method"), "mobile");
@@ -969,6 +986,15 @@ ProjectDialog::ProjectDialog() {
renderer_info = memnew(Label);
renderer_info->set_modulate(Color(1, 1, 1, 0.7));
rvb->add_child(renderer_info);
+
+ rd_not_supported = memnew(Label);
+ rd_not_supported->set_text(TTR("Rendering Device backend not available. Please use the Compatibility renderer."));
+ rd_not_supported->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
+ rd_not_supported->set_custom_minimum_size(Size2(200, 0) * EDSCALE);
+ rd_not_supported->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
+ rd_not_supported->set_visible(false);
+ renderer_container->add_child(rd_not_supported);
+
_renderer_selected();
l = memnew(Label);
diff --git a/editor/project_manager/project_dialog.h b/editor/project_manager/project_dialog.h
index 559147e7c94b..875b19a57b19 100644
--- a/editor/project_manager/project_dialog.h
+++ b/editor/project_manager/project_dialog.h
@@ -79,6 +79,8 @@ class ProjectDialog : public ConfirmationDialog {
Label *renderer_info = nullptr;
HBoxContainer *default_files_container = nullptr;
Ref renderer_button_group;
+ bool rendering_device_supported = false;
+ Label *rd_not_supported = nullptr;
Label *msg = nullptr;
LineEdit *project_name = nullptr;
diff --git a/main/main.cpp b/main/main.cpp
index 3841eb6c1ee3..86427b5d44f7 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -1963,6 +1963,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
GLOBAL_DEF_RST("rendering/rendering_device/fallback_to_vulkan", true);
GLOBAL_DEF_RST("rendering/rendering_device/fallback_to_d3d12", true);
+ GLOBAL_DEF_RST("rendering/rendering_device/fallback_to_opengl3", true);
}
{
@@ -2214,15 +2215,12 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
}
}
- // note this is the desired rendering driver, it doesn't mean we will get it.
- // TODO - make sure this is updated in the case of fallbacks, so that the user interface
- // shows the correct driver string.
- OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
- OS::get_singleton()->set_current_rendering_method(rendering_method);
-
// always convert to lower case for consistency in the code
rendering_driver = rendering_driver.to_lower();
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
+ OS::get_singleton()->set_current_rendering_method(rendering_method);
+
if (use_custom_res) {
if (!force_res) {
window_size.width = GLOBAL_GET("display/window/size/viewport_width");
@@ -2754,6 +2752,8 @@ Error Main::setup2(bool p_show_boot_logo) {
Error err;
display_server = DisplayServer::create(display_driver_idx, rendering_driver, window_mode, window_vsync_mode, window_flags, window_position, window_size, init_screen, context, err);
if (err != OK || display_server == nullptr) {
+ String last_name = DisplayServer::get_create_function_name(display_driver_idx);
+
// We can't use this display server, try other ones as fallback.
// Skip headless (always last registered) because that's not what users
// would expect if they didn't request it explicitly.
@@ -2761,6 +2761,9 @@ Error Main::setup2(bool p_show_boot_logo) {
if (i == display_driver_idx) {
continue; // Don't try the same twice.
}
+ String name = DisplayServer::get_create_function_name(i);
+ WARN_PRINT(vformat("Display driver %s failed, falling back to %s.", last_name, name));
+
display_server = DisplayServer::create(i, rendering_driver, window_mode, window_vsync_mode, window_flags, window_position, window_size, init_screen, context, err);
if (err == OK && display_server != nullptr) {
break;
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index b88d887af52c..145f9784fd01 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -589,12 +589,6 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis
native_menu = memnew(NativeMenu);
-#if defined(GLES3_ENABLED)
- if (rendering_driver == "opengl3") {
- RasterizerGLES3::make_current(false);
- }
-#endif
-
#if defined(RD_ENABLED)
rendering_context = nullptr;
rendering_device = nullptr;
@@ -607,13 +601,26 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis
if (rendering_context) {
if (rendering_context->initialize() != OK) {
- ERR_PRINT(vformat("Failed to initialize %s context", rendering_driver));
memdelete(rendering_context);
rendering_context = nullptr;
- r_error = ERR_UNAVAILABLE;
- return;
+#if defined(GLES3_ENABLED)
+ bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3");
+ if (fallback_to_opengl3 && rendering_driver != "opengl3") {
+ WARN_PRINT("Your device seem not to support Vulkan, switching to OpenGL 3.");
+ rendering_driver = "opengl3";
+ OS::get_singleton()->set_current_rendering_method("gl_compatibility");
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
+ } else
+#endif
+ {
+ ERR_PRINT(vformat("Failed to initialize %s context", rendering_driver));
+ r_error = ERR_UNAVAILABLE;
+ return;
+ }
}
+ }
+ if (rendering_context) {
union {
#ifdef VULKAN_ENABLED
RenderingContextDriverVulkanAndroid::WindowPlatformData vulkan;
@@ -653,6 +660,12 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis
}
#endif
+#if defined(GLES3_ENABLED)
+ if (rendering_driver == "opengl3") {
+ RasterizerGLES3::make_current(false);
+ }
+#endif
+
Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events);
r_error = OK;
diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
index eaa79163fb50..4e0ee85773df 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
@@ -473,12 +473,17 @@ class Godot(private val context: Context) {
// ...add to FrameLayout
containerLayout?.addView(editText)
renderView = if (usesVulkan()) {
- if (!meetsVulkanRequirements(activity.packageManager)) {
+ if (meetsVulkanRequirements(activity.packageManager)) {
+ GodotVulkanRenderView(host, this, godotInputHandler)
+ } else if (canFallbackToOpenGL()) {
+ // Fallback to OpenGl.
+ GodotGLRenderView(host, this, godotInputHandler, xrMode, useDebugOpengl)
+ } else {
throw IllegalStateException(activity.getString(R.string.error_missing_vulkan_requirements_message))
}
- GodotVulkanRenderView(host, this, godotInputHandler)
+
} else {
- // Fallback to openGl
+ // Fallback to OpenGl.
GodotGLRenderView(host, this, godotInputHandler, xrMode, useDebugOpengl)
}
@@ -812,6 +817,13 @@ class Godot(private val context: Context) {
return ("forward_plus" == renderer || "mobile" == renderer) && "vulkan" == renderingDevice
}
+ /**
+ * Returns true if can fallback to OpenGL.
+ */
+ private fun canFallbackToOpenGL(): Boolean {
+ return java.lang.Boolean.parseBoolean(GodotLib.getGlobal("rendering/rendering_device/fallback_to_opengl3"))
+ }
+
/**
* Returns true if the device meets the base requirements for Vulkan support, false otherwise.
*/
diff --git a/platform/ios/display_server_ios.mm b/platform/ios/display_server_ios.mm
index 802fbefc0dbb..600fee75b35f 100644
--- a/platform/ios/display_server_ios.mm
+++ b/platform/ios/display_server_ios.mm
@@ -88,13 +88,26 @@
if (rendering_context) {
if (rendering_context->initialize() != OK) {
- ERR_PRINT(vformat("Failed to initialize %s context", rendering_driver));
memdelete(rendering_context);
rendering_context = nullptr;
- r_error = ERR_UNAVAILABLE;
- return;
+#if defined(GLES3_ENABLED)
+ bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3");
+ if (fallback_to_opengl3 && rendering_driver != "opengl3") {
+ WARN_PRINT("Your device seem not to support MoltenVK or Metal, switching to OpenGL 3.");
+ rendering_driver = "opengl3";
+ OS::get_singleton()->set_current_rendering_method("gl_compatibility");
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
+ } else
+#endif
+ {
+ ERR_PRINT(vformat("Failed to initialize %s context", rendering_driver));
+ r_error = ERR_UNAVAILABLE;
+ return;
+ }
}
+ }
+ if (rendering_context) {
if (rendering_context->window_create(MAIN_WINDOW_ID, &wpd) != OK) {
ERR_PRINT(vformat("Failed to create %s window.", rendering_driver));
memdelete(rendering_context);
diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp
index da4e1aa97cba..d5b1c67550ea 100644
--- a/platform/linuxbsd/wayland/display_server_wayland.cpp
+++ b/platform/linuxbsd/wayland/display_server_wayland.cpp
@@ -1349,23 +1349,50 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
rendering_driver = p_rendering_driver;
+ bool driver_found = false;
+ String executable_name = OS::get_singleton()->get_executable_path().get_file();
+
#ifdef RD_ENABLED
#ifdef VULKAN_ENABLED
if (rendering_driver == "vulkan") {
rendering_context = memnew(RenderingContextDriverVulkanWayland);
}
-#endif
+#endif // VULKAN_ENABLED
if (rendering_context) {
if (rendering_context->initialize() != OK) {
- ERR_PRINT(vformat("Could not initialize %s", rendering_driver));
memdelete(rendering_context);
rendering_context = nullptr;
- r_error = ERR_CANT_CREATE;
- return;
+#if defined(GLES3_ENABLED)
+ bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3");
+ if (fallback_to_opengl3 && rendering_driver != "opengl3") {
+ WARN_PRINT("Your video card drivers seem not to support the required Vulkan version, switching to OpenGL 3.");
+ rendering_driver = "opengl3";
+ OS::get_singleton()->set_current_rendering_method("gl_compatibility");
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
+ } else
+#endif // GLES3_ENABLED
+ {
+ r_error = ERR_CANT_CREATE;
+
+ if (p_rendering_driver == "vulkan") {
+ OS::get_singleton()->alert(
+ vformat("Your video card drivers seem not to support the required Vulkan version.\n\n"
+ "If possible, consider updating your video card drivers or using the OpenGL 3 driver.\n\n"
+ "You can enable the OpenGL 3 driver by starting the engine from the\n"
+ "command line with the command:\n\n \"%s\" --rendering-driver opengl3\n\n"
+ "If you recently updated your video card drivers, try rebooting.",
+ executable_name),
+ "Unable to initialize Vulkan video driver");
+ }
+
+ ERR_FAIL_MSG(vformat("Could not initialize %s", rendering_driver));
+ }
}
+
+ driver_found = true;
}
-#endif
+#endif // RD_ENABLED
#ifdef GLES3_ENABLED
if (rendering_driver == "opengl3" || rendering_driver == "opengl3_es") {
@@ -1429,30 +1456,58 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
if (fallback) {
WARN_PRINT("Your video card drivers seem not to support the required OpenGL version, switching to OpenGLES.");
rendering_driver = "opengl3_es";
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
} else {
r_error = ERR_UNAVAILABLE;
+
+ OS::get_singleton()->alert(
+ vformat("Your video card drivers seem not to support the required OpenGL 3.3 version.\n\n"
+ "If possible, consider updating your video card drivers or using the Vulkan driver.\n\n"
+ "You can enable the Vulkan driver by starting the engine from the\n"
+ "command line with the command:\n\n \"%s\" --rendering-driver vulkan\n\n"
+ "If you recently updated your video card drivers, try rebooting.",
+ executable_name),
+ "Unable to initialize OpenGL video driver");
+
ERR_FAIL_MSG("Could not initialize OpenGL.");
}
} else {
RasterizerGLES3::make_current(true);
+ driver_found = true;
}
}
if (rendering_driver == "opengl3_es") {
egl_manager = memnew(EGLManagerWaylandGLES);
- if (egl_manager->initialize(wayland_thread.get_wl_display()) != OK) {
+ if (egl_manager->initialize(wayland_thread.get_wl_display()) != OK || egl_manager->open_display(wayland_thread.get_wl_display()) != OK) {
memdelete(egl_manager);
egl_manager = nullptr;
r_error = ERR_CANT_CREATE;
- ERR_FAIL_MSG("Could not initialize GLES3.");
+
+ OS::get_singleton()->alert(
+ vformat("Your video card drivers seem not to support the required OpenGL ES 3.0 version.\n\n"
+ "If possible, consider updating your video card drivers or using the Vulkan driver.\n\n"
+ "You can enable the Vulkan driver by starting the engine from the\n"
+ "command line with the command:\n\n \"%s\" --rendering-driver vulkan\n\n"
+ "If you recently updated your video card drivers, try rebooting.",
+ executable_name),
+ "Unable to initialize OpenGL ES video driver");
+
+ ERR_FAIL_MSG("Could not initialize OpenGL ES.");
}
RasterizerGLES3::make_current(false);
+ driver_found = true;
}
}
#endif // GLES3_ENABLED
+ if (!driver_found) {
+ r_error = ERR_UNAVAILABLE;
+ ERR_FAIL_MSG("Video driver not found.");
+ }
+
cursor_set_shape(CURSOR_BUSY);
WindowData &wd = main_window;
@@ -1481,12 +1536,12 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
RendererCompositorRD::make_current();
}
-#endif
+#endif // RD_ENABLED
#ifdef DBUS_ENABLED
portal_desktop = memnew(FreeDesktopPortalDesktop);
screensaver = memnew(FreeDesktopScreenSaver);
-#endif
+#endif // DBUS_ENABLED
screen_set_keep_on(GLOBAL_GET("display/window/energy_saving/keep_screen_on"));
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index af4e3de71791..4071f9dea173 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -2055,7 +2055,7 @@ void DisplayServerX11::window_set_current_screen(int p_screen, WindowID p_window
return;
}
- if (window_get_mode(p_window) == WINDOW_MODE_FULLSCREEN) {
+ if (window_get_mode(p_window) == WINDOW_MODE_FULLSCREEN || window_get_mode(p_window) == WINDOW_MODE_MAXIMIZED) {
Point2i position = screen_get_position(p_screen);
Size2i size = screen_get_size(p_screen);
@@ -5428,25 +5428,6 @@ Vector DisplayServerX11::get_rendering_drivers_func() {
DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerX11(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, p_context, r_error));
- if (r_error != OK) {
- if (p_rendering_driver == "vulkan") {
- String executable_name = OS::get_singleton()->get_executable_path().get_file();
- OS::get_singleton()->alert(
- vformat("Your video card drivers seem not to support the required Vulkan version.\n\n"
- "If possible, consider updating your video card drivers or using the OpenGL 3 driver.\n\n"
- "You can enable the OpenGL 3 driver by starting the engine from the\n"
- "command line with the command:\n\n \"%s\" --rendering-driver opengl3\n\n"
- "If you recently updated your video card drivers, try rebooting.",
- executable_name),
- "Unable to initialize Vulkan video driver");
- } else {
- OS::get_singleton()->alert(
- "Your video card drivers seem not to support the required OpenGL 3.3 version.\n\n"
- "If possible, consider updating your video card drivers.\n\n"
- "If you recently updated your video card drivers, try rebooting.",
- "Unable to initialize OpenGL video driver");
- }
- }
return ds;
}
@@ -6160,25 +6141,51 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
rendering_driver = p_rendering_driver;
bool driver_found = false;
+ String executable_name = OS::get_singleton()->get_executable_path().get_file();
+
+ // Initialize context and rendering device.
+
#if defined(RD_ENABLED)
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
rendering_context = memnew(RenderingContextDriverVulkanX11);
}
-#endif
+#endif // VULKAN_ENABLED
if (rendering_context) {
if (rendering_context->initialize() != OK) {
- ERR_PRINT(vformat("Could not initialize %s", rendering_driver));
memdelete(rendering_context);
rendering_context = nullptr;
- r_error = ERR_CANT_CREATE;
- return;
+#if defined(GLES3_ENABLED)
+ bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3");
+ if (fallback_to_opengl3 && rendering_driver != "opengl3") {
+ WARN_PRINT("Your video card drivers seem not to support the required Vulkan version, switching to OpenGL 3.");
+ rendering_driver = "opengl3";
+ OS::get_singleton()->set_current_rendering_method("gl_compatibility");
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
+ } else
+#endif // GLES3_ENABLED
+ {
+ r_error = ERR_CANT_CREATE;
+
+ if (p_rendering_driver == "vulkan") {
+ OS::get_singleton()->alert(
+ vformat("Your video card drivers seem not to support the required Vulkan version.\n\n"
+ "If possible, consider updating your video card drivers or using the OpenGL 3 driver.\n\n"
+ "You can enable the OpenGL 3 driver by starting the engine from the\n"
+ "command line with the command:\n\n \"%s\" --rendering-driver opengl3\n\n"
+ "If you recently updated your video card drivers, try rebooting.",
+ executable_name),
+ "Unable to initialize Vulkan video driver");
+ }
+
+ ERR_FAIL_MSG(vformat("Could not initialize %s", rendering_driver));
+ }
}
driver_found = true;
}
-#endif
- // Initialize context and rendering device.
+#endif // RD_ENABLED
+
#if defined(GLES3_ENABLED)
if (rendering_driver == "opengl3" || rendering_driver == "opengl3_es") {
if (getenv("DRI_PRIME") == nullptr) {
@@ -6231,8 +6238,19 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
if (fallback) {
WARN_PRINT("Your video card drivers seem not to support the required OpenGL version, switching to OpenGLES.");
rendering_driver = "opengl3_es";
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
} else {
r_error = ERR_UNAVAILABLE;
+
+ OS::get_singleton()->alert(
+ vformat("Your video card drivers seem not to support the required OpenGL 3.3 version.\n\n"
+ "If possible, consider updating your video card drivers or using the Vulkan driver.\n\n"
+ "You can enable the Vulkan driver by starting the engine from the\n"
+ "command line with the command:\n\n \"%s\" --rendering-driver vulkan\n\n"
+ "If you recently updated your video card drivers, try rebooting.",
+ executable_name),
+ "Unable to initialize OpenGL video driver");
+
ERR_FAIL_MSG("Could not initialize OpenGL.");
}
} else {
@@ -6243,20 +6261,28 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
if (rendering_driver == "opengl3_es") {
gl_manager_egl = memnew(GLManagerEGL_X11);
- if (gl_manager_egl->initialize() != OK) {
+ if (gl_manager_egl->initialize() != OK || gl_manager_egl->open_display(x11_display) != OK) {
memdelete(gl_manager_egl);
gl_manager_egl = nullptr;
r_error = ERR_UNAVAILABLE;
- ERR_FAIL_MSG("Could not initialize OpenGLES.");
+
+ OS::get_singleton()->alert(
+ "Your video card drivers seem not to support the required OpenGL ES 3.0 version.\n\n"
+ "If possible, consider updating your video card drivers.\n\n"
+ "If you recently updated your video card drivers, try rebooting.",
+ "Unable to initialize OpenGL ES video driver");
+
+ ERR_FAIL_MSG("Could not initialize OpenGL ES.");
}
driver_found = true;
RasterizerGLES3::make_current(false);
}
-#endif
+#endif // GLES3_ENABLED
+
if (!driver_found) {
r_error = ERR_UNAVAILABLE;
- ERR_FAIL_MSG("Video driver not found");
+ ERR_FAIL_MSG("Video driver not found.");
}
Point2i window_position;
@@ -6297,7 +6323,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
RendererCompositorRD::make_current();
}
-#endif
+#endif // RD_ENABLED
{
//set all event master mask
@@ -6450,7 +6476,8 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
screen_set_keep_on(GLOBAL_GET("display/window/energy_saving/keep_screen_on"));
portal_desktop = memnew(FreeDesktopPortalDesktop);
-#endif
+#endif // DBUS_ENABLED
+
XSetErrorHandler(&default_window_error_handler);
r_error = OK;
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index 22586a777586..51f5ea6c0791 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -1885,6 +1885,12 @@
was_fullscreen = true;
}
+ bool was_maximized = false;
+ if (!was_fullscreen && NSEqualRects([wd.window_object frame], [[wd.window_object screen] visibleFrame])) {
+ [wd.window_object zoom:nil];
+ was_maximized = true;
+ }
+
Rect2i srect = screen_get_usable_rect(p_screen);
Point2i wpos = window_get_position(p_window) - screen_get_position(window_get_current_screen(p_window));
Size2i wsize = window_get_size(p_window);
@@ -1893,6 +1899,10 @@
wpos = wpos.clamp(srect.position, srect.position + srect.size - wsize / 3);
window_set_position(wpos, p_window);
+ if (was_maximized) {
+ [wd.window_object zoom:nil];
+ }
+
if (was_fullscreen) {
// Re-enter fullscreen mode.
[wd.window_object toggleFullScreen:nil];
@@ -3590,6 +3600,34 @@
//TODO - do Vulkan and OpenGL support checks, driver selection and fallback
rendering_driver = p_rendering_driver;
+#if defined(RD_ENABLED)
+#if defined(VULKAN_ENABLED)
+ if (rendering_driver == "vulkan") {
+ rendering_context = memnew(RenderingContextDriverVulkanMacOS);
+ }
+#endif
+
+ if (rendering_context) {
+ if (rendering_context->initialize() != OK) {
+ memdelete(rendering_context);
+ rendering_context = nullptr;
+#if defined(GLES3_ENABLED)
+ bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3");
+ if (fallback_to_opengl3 && rendering_driver != "opengl3") {
+ WARN_PRINT("Your device seem not to support MoltenVK or Metal, switching to OpenGL 3.");
+ rendering_driver = "opengl3";
+ OS::get_singleton()->set_current_rendering_method("gl_compatibility");
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
+ } else
+#endif
+ {
+ r_error = ERR_CANT_CREATE;
+ ERR_FAIL_MSG("Could not initialize " + rendering_driver);
+ }
+ }
+ }
+#endif
+
#if defined(GLES3_ENABLED)
if (rendering_driver == "opengl3_angle") {
gl_manager_angle = memnew(GLManagerANGLE_MacOS);
@@ -3598,8 +3636,13 @@
gl_manager_angle = nullptr;
bool fallback = GLOBAL_GET("rendering/gl_compatibility/fallback_to_native");
if (fallback) {
- WARN_PRINT("Your video card drivers seem not to support the required Metal version, switching to native OpenGL.");
+#ifdef EGL_STATIC
+ WARN_PRINT("Your video card drivers seem not to support GLES3 / ANGLE, switching to native OpenGL.");
+#else
+ WARN_PRINT("Your video card drivers seem not to support GLES3 / ANGLE or ANGLE dynamic libraries (libEGL.dylib and libGLESv2.dylib) are missing, switching to native OpenGL.");
+#endif
rendering_driver = "opengl3";
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
} else {
r_error = ERR_UNAVAILABLE;
ERR_FAIL_MSG("Could not initialize ANGLE OpenGL.");
@@ -3617,22 +3660,6 @@
}
}
#endif
-#if defined(RD_ENABLED)
-#if defined(VULKAN_ENABLED)
- if (rendering_driver == "vulkan") {
- rendering_context = memnew(RenderingContextDriverVulkanMacOS);
- }
-#endif
-
- if (rendering_context) {
- if (rendering_context->initialize() != OK) {
- memdelete(rendering_context);
- rendering_context = nullptr;
- r_error = ERR_CANT_CREATE;
- ERR_FAIL_MSG("Could not initialize " + rendering_driver);
- }
- }
-#endif
Point2i window_position;
if (p_position != nullptr) {
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index ef5644c7d884..cf8a39341d78 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -1501,6 +1501,7 @@ DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mod
rendering_device->screen_create(window_id);
}
#endif
+ wd.initialized = true;
return window_id;
}
@@ -1794,6 +1795,13 @@ void DisplayServerWindows::window_set_current_screen(int p_screen, WindowID p_wi
Size2 size = screen_get_size(p_screen);
MoveWindow(wd.hWnd, pos.x, pos.y, size.width, size.height, TRUE);
+ } else if (wd.maximized) {
+ Point2 pos = screen_get_position(p_screen) + _get_screens_origin();
+ Size2 size = screen_get_size(p_screen);
+
+ ShowWindow(wd.hWnd, SW_RESTORE);
+ MoveWindow(wd.hWnd, pos.x, pos.y, size.width, size.height, TRUE);
+ ShowWindow(wd.hWnd, SW_MAXIMIZE);
} else {
Rect2i srect = screen_get_usable_rect(p_screen);
Point2i wpos = window_get_position(p_window) - screen_get_position(window_get_current_screen(p_window));
@@ -2039,7 +2047,7 @@ Size2i DisplayServerWindows::window_get_size_with_decorations(WindowID p_window)
return Size2();
}
-void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_maximized, bool p_maximized_fs, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex) {
+void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_initialized, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_minimized, bool p_maximized, bool p_maximized_fs, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex) {
// Windows docs for window styles:
// https://docs.microsoft.com/en-us/windows/win32/winmsg/window-styles
// https://docs.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles
@@ -2048,12 +2056,16 @@ void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscre
r_style_ex = WS_EX_WINDOWEDGE;
if (p_main_window) {
r_style_ex |= WS_EX_APPWINDOW;
- r_style |= WS_VISIBLE;
+ if (p_initialized) {
+ r_style |= WS_VISIBLE;
+ }
}
if (p_fullscreen || p_borderless) {
r_style |= WS_POPUP; // p_borderless was WS_EX_TOOLWINDOW in the past.
- if (p_maximized) {
+ if (p_minimized) {
+ r_style |= WS_MINIMIZE;
+ } else if (p_maximized) {
r_style |= WS_MAXIMIZE;
}
if (!p_fullscreen) {
@@ -2068,13 +2080,19 @@ void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscre
}
} else {
if (p_resizable) {
- if (p_maximized) {
+ if (p_minimized) {
+ r_style = WS_OVERLAPPEDWINDOW | WS_MINIMIZE;
+ } else if (p_maximized) {
r_style = WS_OVERLAPPEDWINDOW | WS_MAXIMIZE;
} else {
r_style = WS_OVERLAPPEDWINDOW;
}
} else {
- r_style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
+ if (p_minimized) {
+ r_style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MINIMIZE;
+ } else {
+ r_style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
+ }
}
}
@@ -2082,7 +2100,7 @@ void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscre
r_style_ex |= WS_EX_TOPMOST | WS_EX_NOACTIVATE;
}
- if (!p_borderless && !p_no_activate_focus) {
+ if (!p_borderless && !p_no_activate_focus && p_initialized) {
r_style |= WS_VISIBLE;
}
@@ -2099,7 +2117,7 @@ void DisplayServerWindows::_update_window_style(WindowID p_window, bool p_repain
DWORD style = 0;
DWORD style_ex = 0;
- _get_window_style(p_window == MAIN_WINDOW_ID, wd.fullscreen, wd.multiwindow_fs, wd.borderless, wd.resizable, wd.maximized, wd.maximized_fs, wd.no_focus || wd.is_popup, style, style_ex);
+ _get_window_style(p_window == MAIN_WINDOW_ID, wd.initialized, wd.fullscreen, wd.multiwindow_fs, wd.borderless, wd.resizable, wd.minimized, wd.maximized, wd.maximized_fs, wd.no_focus || wd.is_popup, style, style_ex);
SetWindowLongPtr(wd.hWnd, GWL_STYLE, style);
SetWindowLongPtr(wd.hWnd, GWL_EXSTYLE, style_ex);
@@ -5510,7 +5528,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
DWORD dwExStyle;
DWORD dwStyle;
- _get_window_style(window_id_counter == MAIN_WINDOW_ID, (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN), p_mode != WINDOW_MODE_EXCLUSIVE_FULLSCREEN, p_flags & WINDOW_FLAG_BORDERLESS_BIT, !(p_flags & WINDOW_FLAG_RESIZE_DISABLED_BIT), p_mode == WINDOW_MODE_MAXIMIZED, false, (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) | (p_flags & WINDOW_FLAG_POPUP), dwStyle, dwExStyle);
+ _get_window_style(window_id_counter == MAIN_WINDOW_ID, false, (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN), p_mode != WINDOW_MODE_EXCLUSIVE_FULLSCREEN, p_flags & WINDOW_FLAG_BORDERLESS_BIT, !(p_flags & WINDOW_FLAG_RESIZE_DISABLED_BIT), p_mode == WINDOW_MODE_MINIMIZED, p_mode == WINDOW_MODE_MAXIMIZED, false, (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) | (p_flags & WINDOW_FLAG_POPUP), dwStyle, dwExStyle);
RECT WindowRect;
@@ -5779,6 +5797,8 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
return id;
}
+BitField DisplayServerWindows::tested_drivers = 0;
+
// WinTab API.
bool DisplayServerWindows::wintab_available = false;
WTOpenPtr DisplayServerWindows::wintab_WTOpen = nullptr;
@@ -5935,6 +5955,8 @@ void DisplayServerWindows::tablet_set_current_driver(const String &p_driver) {
DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, Error &r_error) {
KeyMappingWindows::initialize();
+ tested_drivers.clear();
+
drop_events = false;
key_event_pos = 0;
@@ -6103,7 +6125,6 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
wc.lpszClassName = L"Engine";
if (!RegisterClassExW(&wc)) {
- MessageBoxW(nullptr, L"Failed To Register The Window Class.", L"ERROR", MB_OK | MB_ICONEXCLAMATION);
r_error = ERR_UNAVAILABLE;
return;
}
@@ -6114,11 +6135,13 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
rendering_context = memnew(RenderingContextDriverVulkanWindows);
+ tested_drivers.set_flag(DRIVER_ID_RD_VULKAN);
}
#endif
#if defined(D3D12_ENABLED)
if (rendering_driver == "d3d12") {
rendering_context = memnew(RenderingContextDriverD3D12);
+ tested_drivers.set_flag(DRIVER_ID_RD_D3D12);
}
#endif
@@ -6130,9 +6153,11 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
if (failed && fallback_to_vulkan && rendering_driver != "vulkan") {
memdelete(rendering_context);
rendering_context = memnew(RenderingContextDriverVulkanWindows);
+ tested_drivers.set_flag(DRIVER_ID_RD_VULKAN);
if (rendering_context->initialize() == OK) {
WARN_PRINT("Your video card drivers seem not to support Direct3D 12, switching to Vulkan.");
rendering_driver = "vulkan";
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
failed = false;
}
}
@@ -6142,12 +6167,27 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
if (failed && fallback_to_d3d12 && rendering_driver != "d3d12") {
memdelete(rendering_context);
rendering_context = memnew(RenderingContextDriverD3D12);
+ tested_drivers.set_flag(DRIVER_ID_RD_D3D12);
if (rendering_context->initialize() == OK) {
WARN_PRINT("Your video card drivers seem not to support Vulkan, switching to Direct3D 12.");
rendering_driver = "d3d12";
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
failed = false;
}
}
+#endif
+#if defined(GLES3_ENABLED)
+ bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3");
+ if (failed && fallback_to_opengl3 && rendering_driver != "opengl3") {
+ memdelete(rendering_context);
+ rendering_context = nullptr;
+ tested_drivers.set_flag(DRIVER_ID_COMPAT_OPENGL3);
+ WARN_PRINT("Your video card drivers seem not to support Direct3D 12 or Vulkan, switching to OpenGL 3.");
+ rendering_driver = "opengl3";
+ OS::get_singleton()->set_current_rendering_method("gl_compatibility");
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
+ failed = false;
+ }
#endif
if (failed) {
memdelete(rendering_context);
@@ -6187,10 +6227,12 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
#endif
}
+ bool gl_supported = true;
if (fallback && (rendering_driver == "opengl3")) {
Dictionary gl_info = detect_wgl();
bool force_angle = false;
+ gl_supported = gl_info["version"].operator int() >= 30003;
Vector2i device_id = _get_device_ids(gl_info["name"]);
Array device_list = GLOBAL_GET("rendering/gl_compatibility/force_angle_on_devices");
@@ -6212,39 +6254,59 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
}
if (force_angle || (gl_info["version"].operator int() < 30003)) {
+ tested_drivers.set_flag(DRIVER_ID_COMPAT_OPENGL3);
if (show_warning) {
- WARN_PRINT("Your video card drivers seem not to support the required OpenGL 3.3 version, switching to ANGLE.");
+ if (gl_info["version"].operator int() < 30003) {
+ WARN_PRINT("Your video card drivers seem not to support the required OpenGL 3.3 version, switching to ANGLE.");
+ } else {
+ WARN_PRINT("Your video card drivers are known to have low quality OpenGL 3.3 support, switching to ANGLE.");
+ }
}
rendering_driver = "opengl3_angle";
+ OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
}
}
+ if (rendering_driver == "opengl3_angle") {
+ gl_manager_angle = memnew(GLManagerANGLE_Windows);
+ tested_drivers.set_flag(DRIVER_ID_COMPAT_ANGLE_D3D11);
+
+ if (gl_manager_angle->initialize() != OK) {
+ memdelete(gl_manager_angle);
+ gl_manager_angle = nullptr;
+ bool fallback_to_native = GLOBAL_GET("rendering/gl_compatibility/fallback_to_native");
+ if (fallback_to_native && gl_supported) {
+#ifdef EGL_STATIC
+ WARN_PRINT("Your video card drivers seem not to support GLES3 / ANGLE, switching to native OpenGL.");
+#else
+ WARN_PRINT("Your video card drivers seem not to support GLES3 / ANGLE or ANGLE dynamic libraries (libEGL.dll and libGLESv2.dll) are missing, switching to native OpenGL.");
+#endif
+ rendering_driver = "opengl3";
+ } else {
+ r_error = ERR_UNAVAILABLE;
+ ERR_FAIL_MSG("Could not initialize ANGLE OpenGL.");
+ }
+ }
+ }
if (rendering_driver == "opengl3") {
gl_manager_native = memnew(GLManagerNative_Windows);
+ tested_drivers.set_flag(DRIVER_ID_COMPAT_OPENGL3);
if (gl_manager_native->initialize() != OK) {
memdelete(gl_manager_native);
gl_manager_native = nullptr;
r_error = ERR_UNAVAILABLE;
- return;
+ ERR_FAIL_MSG("Could not initialize native OpenGL.");
}
+ }
+ if (rendering_driver == "opengl3") {
RasterizerGLES3::make_current(true);
}
if (rendering_driver == "opengl3_angle") {
- gl_manager_angle = memnew(GLManagerANGLE_Windows);
-
- if (gl_manager_angle->initialize() != OK) {
- memdelete(gl_manager_angle);
- gl_manager_angle = nullptr;
- r_error = ERR_UNAVAILABLE;
- return;
- }
-
RasterizerGLES3::make_current(false);
}
#endif
-
String appname;
if (Engine::get_singleton()->is_editor_hint()) {
appname = "Blazium.GodotEditor." + String(EXTERNAL_VERSION_FULL_CONFIG);
@@ -6290,7 +6352,10 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
}
WindowID main_window = _create_window(p_mode, p_vsync_mode, p_flags, Rect2i(window_position, p_resolution), false, INVALID_WINDOW_ID);
- ERR_FAIL_COND_MSG(main_window == INVALID_WINDOW_ID, "Failed to create main window.");
+ if (main_window == INVALID_WINDOW_ID) {
+ r_error = ERR_UNAVAILABLE;
+ ERR_FAIL_MSG("Failed to create main window.");
+ }
joypad = new JoypadWindows(&windows[MAIN_WINDOW_ID].hWnd);
@@ -6300,6 +6365,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
}
}
+ windows[MAIN_WINDOW_ID].initialized = true;
show_window(MAIN_WINDOW_ID);
#if defined(RD_ENABLED)
@@ -6366,32 +6432,41 @@ Vector DisplayServerWindows::get_rendering_drivers_func() {
DisplayServer *DisplayServerWindows::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerWindows(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, p_context, r_error));
if (r_error != OK) {
- if (p_rendering_driver == "vulkan") {
- String executable_name = OS::get_singleton()->get_executable_path().get_file();
- OS::get_singleton()->alert(
- vformat("Your video card drivers seem not to support the required Vulkan version.\n\n"
- "If possible, consider updating your video card drivers or using the OpenGL 3 driver.\n\n"
- "You can enable the OpenGL 3 driver by starting the engine from the\n"
- "command line with the command:\n\n \"%s\" --rendering-driver opengl3\n\n"
- "If you have recently updated your video card drivers, try rebooting.",
- executable_name),
- "Unable to initialize Vulkan video driver");
- } else if (p_rendering_driver == "d3d12") {
+ if (tested_drivers == 0) {
+ OS::get_singleton()->alert("Failed to register the window class.", "Unable to initialize DisplayServer");
+ } else if (tested_drivers.has_flag(DRIVER_ID_RD_VULKAN) || tested_drivers.has_flag(DRIVER_ID_RD_D3D12)) {
+ Vector drivers;
+ if (tested_drivers.has_flag(DRIVER_ID_RD_VULKAN)) {
+ drivers.push_back("Vulkan");
+ }
+ if (tested_drivers.has_flag(DRIVER_ID_RD_D3D12)) {
+ drivers.push_back("Direct3D 12");
+ }
String executable_name = OS::get_singleton()->get_executable_path().get_file();
OS::get_singleton()->alert(
- vformat("Your video card drivers seem not to support the required DirectX 12 version.\n\n"
+ vformat("Your video card drivers seem not to support the required %s version.\n\n"
"If possible, consider updating your video card drivers or using the OpenGL 3 driver.\n\n"
"You can enable the OpenGL 3 driver by starting the engine from the\n"
"command line with the command:\n\n \"%s\" --rendering-driver opengl3\n\n"
"If you have recently updated your video card drivers, try rebooting.",
+ String(" or ").join(drivers),
executable_name),
- "Unable to initialize DirectX 12 video driver");
+ "Unable to initialize video driver");
} else {
+ Vector drivers;
+ if (tested_drivers.has_flag(DRIVER_ID_COMPAT_OPENGL3)) {
+ drivers.push_back("OpenGL 3.3");
+ }
+ if (tested_drivers.has_flag(DRIVER_ID_COMPAT_ANGLE_D3D11)) {
+ drivers.push_back("Direct3D 11");
+ }
OS::get_singleton()->alert(
- "Your video card drivers seem not to support the required OpenGL 3.3 version.\n\n"
- "If possible, consider updating your video card drivers.\n\n"
- "If you have recently updated your video card drivers, try rebooting.",
- "Unable to initialize OpenGL video driver");
+ vformat(
+ "Your video card drivers seem not to support the required %s version.\n\n"
+ "If possible, consider updating your video card drivers.\n\n"
+ "If you have recently updated your video card drivers, try rebooting.",
+ String(" or ").join(drivers)),
+ "Unable to initialize video driver");
}
}
return ds;
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index 03132bb0dbc9..7d6a3e96a6bc 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -394,6 +394,14 @@ class DisplayServerWindows : public DisplayServer {
String tablet_driver;
Vector tablet_drivers;
+ enum DriverID {
+ DRIVER_ID_COMPAT_OPENGL3 = 1 << 0,
+ DRIVER_ID_COMPAT_ANGLE_D3D11 = 1 << 1,
+ DRIVER_ID_RD_VULKAN = 1 << 2,
+ DRIVER_ID_RD_D3D12 = 1 << 3,
+ };
+ static BitField tested_drivers;
+
enum TimerID {
TIMER_ID_MOVE_REDRAW = 1,
TIMER_ID_WINDOW_ACTIVATION = 2,
@@ -516,6 +524,8 @@ class DisplayServerWindows : public DisplayServer {
bool is_popup = false;
Rect2i parent_safe_rect;
+
+ bool initialized = false;
};
JoypadWindows *joypad = nullptr;
@@ -583,7 +593,7 @@ class DisplayServerWindows : public DisplayServer {
HashMap pointer_last_pos;
void _send_window_event(const WindowData &wd, WindowEvent p_event);
- void _get_window_style(bool p_main_window, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_maximized, bool p_maximized_fs, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex);
+ void _get_window_style(bool p_main_window, bool p_initialized, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_minimized, bool p_maximized, bool p_maximized_fs, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex);
MouseMode mouse_mode;
int restore_mouse_trails = 0;
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index 54510576459b..8cb3e560ac9f 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -34,6 +34,14 @@
#include "scene/resources/texture.h"
#include "servers/display_server_headless.h"
+#if defined(VULKAN_ENABLED)
+#include "drivers/vulkan/rendering_context_driver_vulkan.h"
+#undef CursorShape
+#endif
+#if defined(D3D12_ENABLED)
+#include "drivers/d3d12/rendering_context_driver_d3d12.h"
+#endif
+
DisplayServer *DisplayServer::singleton = nullptr;
bool DisplayServer::hidpi_allowed = false;
@@ -1211,6 +1219,40 @@ void DisplayServer::_input_set_custom_mouse_cursor_func(const Ref &p_i
singleton->cursor_set_custom_image(p_image, (CursorShape)p_shape, p_hostspot);
}
+bool DisplayServer::can_create_rendering_device() {
+#if defined(RD_ENABLED)
+ Error err;
+ RenderingContextDriver *rcd = nullptr;
+
+#if defined(VULKAN_ENABLED)
+ rcd = memnew(RenderingContextDriverVulkan);
+#endif
+#ifdef D3D12_ENABLED
+ if (rcd == nullptr) {
+ rcd = memnew(RenderingContextDriverD3D12);
+ }
+#endif
+
+ if (rcd != nullptr) {
+ err = rcd->initialize();
+ if (err == OK) {
+ RenderingDevice *rd = memnew(RenderingDevice);
+ err = rd->initialize(rcd);
+ memdelete(rd);
+ rd = nullptr;
+ if (err == OK) {
+ return true;
+ }
+ }
+
+ memdelete(rcd);
+ rcd = nullptr;
+ }
+
+#endif // RD_ENABLED
+ return false;
+}
+
DisplayServer::DisplayServer() {
singleton = this;
Input::set_mouse_mode_func = _input_set_mouse_mode;
diff --git a/servers/display_server.h b/servers/display_server.h
index d0fe76faff37..04f4b0c03d25 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -594,6 +594,8 @@ class DisplayServer : public Object {
static Vector get_create_function_rendering_drivers(int p_index);
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_position, const Vector2i &p_resolution, int p_screen, Context p_context, Error &r_error);
+ static bool can_create_rendering_device();
+
DisplayServer();
~DisplayServer();
};