diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 11578367797..0134cdc230a 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -2366,6 +2366,13 @@ Windows override for [member rendering/gl_compatibility/driver]. + + If [code]true[/code], the compatibility renderer will fall back to ANGLE if native OpenGL is not supported or the device is listed in [member rendering/gl_compatibility/force_angle_on_devices]. + + + An [Array] of devices which should always use the ANGLE renderer. + Each entry is a [Dictionary] with the following keys: [code]vendor[/code] and [code]name[/code]. [code]name[/code] can be set to [code]*[/code] to add all devices with the specified [code]vendor[/code]. + Maximum number of canvas items commands that can be drawn in a single viewport update. If more render commands are issued they will be ignored. Decreasing this limit may improve performance on bandwidth limited devices. Increase this limit if you find that not all objects are being drawn in a frame. diff --git a/main/main.cpp b/main/main.cpp index f0a05fcd638..2ab3fdba7d4 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1752,6 +1752,10 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph #endif String default_driver = driver_hints.get_slice(",", 0); + String default_driver_macos = default_driver; +#if defined(GLES3_ENABLED) && defined(EGL_STATIC) && defined(MACOS_ENABLED) + default_driver_macos = "opengl3_angle"; // Default to ANGLE if it's built-in. +#endif GLOBAL_DEF_RST("rendering/gl_compatibility/driver", default_driver); GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.windows", PROPERTY_HINT_ENUM, driver_hints_angle), default_driver); @@ -1759,8 +1763,11 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.web", PROPERTY_HINT_ENUM, driver_hints), default_driver); GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.android", PROPERTY_HINT_ENUM, driver_hints), default_driver); GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.ios", PROPERTY_HINT_ENUM, driver_hints), default_driver); - GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.macos", PROPERTY_HINT_ENUM, driver_hints_angle), default_driver); + GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.macos", PROPERTY_HINT_ENUM, driver_hints_angle), default_driver_macos); GLOBAL_DEF_RST("rendering/gl_compatibility/nvidia_disable_threaded_optimization", true); + GLOBAL_DEF_RST("rendering/gl_compatibility/fallback_to_angle", true); + + GLOBAL_DEF_RST(PropertyInfo(Variant::ARRAY, "rendering/gl_compatibility/force_angle_on_devices", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::DICTIONARY, PROPERTY_HINT_NONE, String())), Array()); } // Start with RenderingDevice-based backends. Should be included if any RD driver present. diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index d316d14a24f..ed52c5eb922 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -4631,9 +4631,22 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win // Init context and rendering device #if defined(GLES3_ENABLED) - if (rendering_driver == "opengl3") { - int gl_version = detect_wgl_version(); - if (gl_version < 30003) { + bool fallback = GLOBAL_GET("rendering/gl_compatibility/fallback_to_angle"); + if (fallback && (rendering_driver == "opengl3")) { + Dictionary gl_info = detect_wgl(); + + bool force_angle = false; + + Array device_list = GLOBAL_GET("rendering/gl_compatibility/force_angle_on_devices"); + for (int i = 0; i < device_list.size(); i++) { + const Dictionary &device = device_list[i]; + if (device.has("vendor") && device.has("name") && device["vendor"].operator String().to_upper() == gl_info["vendor"].operator String().to_upper() && (device["name"] == "*" || device["name"].operator String().to_upper() == gl_info["name"].operator String().to_upper())) { + force_angle = true; + break; + } + } + + if (force_angle || (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."); rendering_driver = "opengl3_angle"; } diff --git a/platform/windows/wgl_detect_version.cpp b/platform/windows/wgl_detect_version.cpp index 264cd525c5e..49da4b58c7a 100644 --- a/platform/windows/wgl_detect_version.cpp +++ b/platform/windows/wgl_detect_version.cpp @@ -35,6 +35,7 @@ #include "core/string/print_string.h" #include "core/string/ustring.h" +#include "core/variant/dictionary.h" #include @@ -64,9 +65,11 @@ typedef HGLRC(APIENTRY *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int typedef void *(APIENTRY *PFNWGLGETPROCADDRESS)(LPCSTR); typedef const char *(APIENTRY *PFNWGLGETSTRINGPROC)(unsigned int); -int detect_wgl_version() { - int major = 0; - int minor = 0; +Dictionary detect_wgl() { + Dictionary gl_info; + gl_info["version"] = 0; + gl_info["vendor"] = String(); + gl_info["name"] = String(); PFNWGLCREATECONTEXT gd_wglCreateContext; PFNWGLMAKECURRENT gd_wglMakeCurrent; @@ -75,14 +78,14 @@ int detect_wgl_version() { HMODULE module = LoadLibraryW(L"opengl32.dll"); if (!module) { - return 0; + return gl_info; } gd_wglCreateContext = (PFNWGLCREATECONTEXT)GetProcAddress(module, "wglCreateContext"); gd_wglMakeCurrent = (PFNWGLMAKECURRENT)GetProcAddress(module, "wglMakeCurrent"); gd_wglDeleteContext = (PFNWGLDELETECONTEXT)GetProcAddress(module, "wglDeleteContext"); gd_wglGetProcAddress = (PFNWGLGETPROCADDRESS)GetProcAddress(module, "wglGetProcAddress"); if (!gd_wglCreateContext || !gd_wglMakeCurrent || !gd_wglDeleteContext || !gd_wglGetProcAddress) { - return 0; + return gl_info; } LPCWSTR class_name = L"EngineWGLDetect"; @@ -151,8 +154,8 @@ int detect_wgl_version() { }; const char *version = (const char *)gd_wglGetString(WGL_VERSION); if (version) { - const String device_vendor = String::utf8((const char *)gd_wglGetString(WGL_VENDOR)).strip_edges(); - const String device_name = String::utf8((const char *)gd_wglGetString(WGL_RENDERER)).strip_edges(); + const String device_vendor = String::utf8((const char *)gd_wglGetString(WGL_VENDOR)).strip_edges().trim_suffix(" Corporation"); + const String device_name = String::utf8((const char *)gd_wglGetString(WGL_RENDERER)).strip_edges().trim_suffix("/PCIe/SSE2"); for (int i = 0; prefixes[i]; i++) { size_t length = strlen(prefixes[i]); if (strncmp(version, prefixes[i], length) == 0) { @@ -160,12 +163,17 @@ int detect_wgl_version() { break; } } + int major = 0; + int minor = 0; #ifdef _MSC_VER sscanf_s(version, "%d.%d", &major, &minor); #else sscanf(version, "%d.%d", &major, &minor); #endif print_verbose(vformat("Native OpenGL API detected: %d.%d: %s - %s", major, minor, device_vendor, device_name)); + gl_info["vendor"] = device_vendor; + gl_info["name"] = device_name; + gl_info["version"] = major * 10000 + minor; } } } @@ -183,7 +191,7 @@ int detect_wgl_version() { } UnregisterClassW(class_name, hInstance); - return major * 10000 + minor; + return gl_info; } #endif // WINDOWS_ENABLED && GLES3_ENABLED diff --git a/platform/windows/wgl_detect_version.h b/platform/windows/wgl_detect_version.h index 0be2923ba35..c110b1219ef 100644 --- a/platform/windows/wgl_detect_version.h +++ b/platform/windows/wgl_detect_version.h @@ -33,7 +33,9 @@ #if defined(WINDOWS_ENABLED) && defined(GLES3_ENABLED) -int detect_wgl_version(); +class Dictionary; + +Dictionary detect_wgl(); #endif // WINDOWS_ENABLED && GLES3_ENABLED