From 542f8ddf22ab696b70d6f8acfeac95b037fd998b Mon Sep 17 00:00:00 2001 From: Dario Date: Mon, 12 Jan 2026 10:14:36 -0300 Subject: [PATCH] Fix fallback to OpenGL3 from Vulkan initialization on Android. --- core/os/os.h | 59 +++++--- .../display_server_apple_embedded.mm | 4 +- editor/project_manager/project_manager.cpp | 2 +- main/main.cpp | 20 +-- main/main.h | 1 - modules/openxr/register_types.cpp | 2 +- platform/android/display_server_android.cpp | 138 ++++++++++-------- platform/android/display_server_android.h | 6 +- .../main/java/org/godotengine/godot/Godot.kt | 57 +++----- .../java/org/godotengine/godot/GodotLib.java | 11 +- platform/android/java_godot_lib_jni.cpp | 42 +++++- platform/android/java_godot_lib_jni.h | 2 +- .../wayland/display_server_wayland.cpp | 6 +- platform/linuxbsd/x11/display_server_x11.cpp | 6 +- platform/macos/display_server_embedded.mm | 8 +- platform/macos/display_server_macos.mm | 8 +- platform/windows/display_server_windows.cpp | 8 +- 17 files changed, 218 insertions(+), 162 deletions(-) diff --git a/core/os/os.h b/core/os/os.h index 5275a30c92..d15844d790 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -43,6 +43,32 @@ class MainLoop; class OS { +public: + typedef void (*ImeCallback)(void *p_inp, const String &p_text, Point2 p_selection); + typedef bool (*HasServerFeatureCallback)(const String &p_feature); + + enum RenderThreadMode { + RENDER_THREAD_UNSAFE, + RENDER_THREAD_SAFE, + RENDER_SEPARATE_THREAD, + }; + + enum StdHandleType { + STD_HANDLE_INVALID, + STD_HANDLE_CONSOLE, + STD_HANDLE_FILE, + STD_HANDLE_PIPE, + STD_HANDLE_UNKNOWN, + }; + + enum RenderingSource { + RENDERING_SOURCE_DEFAULT, + RENDERING_SOURCE_PROJECT_SETTING, + RENDERING_SOURCE_COMMANDLINE, + RENDERING_SOURCE_FALLBACK + }; + +private: static OS *singleton; static uint64_t target_ticks; String _execpath; @@ -71,7 +97,9 @@ class OS { List restart_commandline; String _current_rendering_driver_name; + RenderingSource _current_rendering_driver_name_source = RENDERING_SOURCE_DEFAULT; String _current_rendering_method; + RenderingSource _current_rendering_method_source = RENDERING_SOURCE_DEFAULT; bool _is_gles_over_gl = false; RemoteFilesystemClient default_rfs; @@ -85,25 +113,6 @@ class OS { protected: void _set_logger(CompositeLogger *p_logger); -public: - typedef void (*ImeCallback)(void *p_inp, const String &p_text, Point2 p_selection); - typedef bool (*HasServerFeatureCallback)(const String &p_feature); - - enum RenderThreadMode { - RENDER_THREAD_UNSAFE, - RENDER_THREAD_SAFE, - RENDER_SEPARATE_THREAD, - }; - - enum StdHandleType { - STD_HANDLE_INVALID, - STD_HANDLE_CONSOLE, - STD_HANDLE_FILE, - STD_HANDLE_PIPE, - STD_HANDLE_UNKNOWN, - }; - -protected: friend class Main; // Needed by tests to setup command-line args. friend int test_main(int argc, char *argv[]); @@ -134,12 +143,20 @@ public: static bool prefer_meta_over_ctrl(); - 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_current_rendering_driver_name(const String &p_driver_name, RenderingSource p_source) { + _current_rendering_driver_name = p_driver_name; + _current_rendering_driver_name_source = p_source; + } + void set_current_rendering_method(const String &p_name, RenderingSource p_source) { + _current_rendering_method = p_name; + _current_rendering_method_source = p_source; + } void set_gles_over_gl(bool p_enabled) { _is_gles_over_gl = p_enabled; } String get_current_rendering_driver_name() const { return _current_rendering_driver_name; } String get_current_rendering_method() const { return _current_rendering_method; } + RenderingSource get_current_rendering_driver_name_source() const { return _current_rendering_driver_name_source; } + RenderingSource get_current_rendering_method_source() const { return _current_rendering_method_source; } bool get_gles_over_gl() const { return _is_gles_over_gl; } virtual Vector get_video_adapter_driver_info() const = 0; diff --git a/drivers/apple_embedded/display_server_apple_embedded.mm b/drivers/apple_embedded/display_server_apple_embedded.mm index 83d78962ee..b41b66e22b 100644 --- a/drivers/apple_embedded/display_server_apple_embedded.mm +++ b/drivers/apple_embedded/display_server_apple_embedded.mm @@ -114,8 +114,8 @@ DisplayServerAppleEmbedded::DisplayServerAppleEmbedded(const String &p_rendering if (fallback_to_opengl3 && rendering_driver != "opengl3") { WARN_PRINT("Your device does not seem 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); + OS::get_singleton()->set_current_rendering_method("gl_compatibility", OS::RENDERING_SOURCE_FALLBACK); + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver, OS::RENDERING_SOURCE_FALLBACK); } else #endif { diff --git a/editor/project_manager/project_manager.cpp b/editor/project_manager/project_manager.cpp index b47e0c9bbf..7f24d8539e 100644 --- a/editor/project_manager/project_manager.cpp +++ b/editor/project_manager/project_manager.cpp @@ -1191,7 +1191,7 @@ void ProjectManager::_perform_full_project_conversion() { args.push_back(path); args.push_back("--convert-3to4"); args.push_back("--rendering-driver"); - args.push_back(Main::get_rendering_driver_name()); + args.push_back(OS::get_singleton()->get_current_rendering_driver_name()); Error err = OS::get_singleton()->create_instance(args); ERR_FAIL_COND(err); diff --git a/main/main.cpp b/main/main.cpp index 064c20dab4..a598400bc1 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -196,8 +196,6 @@ static bool _start_success = false; String display_driver = ""; String tablet_driver = ""; String text_driver = ""; -String rendering_driver = ""; -String rendering_method = ""; static int text_driver_idx = -1; static int audio_driver_idx = -1; @@ -1083,6 +1081,10 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph bool delta_smoothing_override = false; bool load_shell_env = false; + String rendering_driver = ""; + String rendering_method = ""; + OS::RenderingSource rendering_driver_source = OS::RenderingSource::RENDERING_SOURCE_DEFAULT; + OS::RenderingSource rendering_method_source = OS::RenderingSource::RENDERING_SOURCE_DEFAULT; String default_renderer = ""; String default_renderer_mobile = ""; String renderer_hints = ""; @@ -1280,6 +1282,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } else if (arg == "--rendering-driver") { if (N) { rendering_driver = N->get(); + rendering_driver_source = OS::RenderingSource::RENDERING_SOURCE_COMMANDLINE; N = N->next(); } else { OS::get_singleton()->print("Missing rendering driver argument, aborting.\n"); @@ -2571,6 +2574,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph // Default to ProjectSettings default if nothing set on the command line. if (rendering_method.is_empty()) { rendering_method = GLOBAL_GET("rendering/renderer/rendering_method"); + rendering_method_source = OS::RenderingSource::RENDERING_SOURCE_PROJECT_SETTING; } if (rendering_driver.is_empty()) { @@ -2578,16 +2582,18 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph rendering_driver = "dummy"; } else if (rendering_method == "gl_compatibility") { rendering_driver = GLOBAL_GET("rendering/gl_compatibility/driver"); + rendering_driver_source = OS::RenderingSource::RENDERING_SOURCE_PROJECT_SETTING; } else { rendering_driver = GLOBAL_GET("rendering/rendering_device/driver"); + rendering_driver_source = OS::RenderingSource::RENDERING_SOURCE_PROJECT_SETTING; } } // 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); + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver, rendering_driver_source); + OS::get_singleton()->set_current_rendering_method(rendering_method, rendering_method_source); #ifdef TOOLS_ENABLED if (!force_res && project_manager) { @@ -3225,7 +3231,7 @@ Error Main::setup2(bool p_show_boot_logo) { } DisplayServer::accessibility_set_mode(accessibility_mode); - // rendering_driver now held in static global String in main and initialized in setup() + String rendering_driver = OS::get_singleton()->get_current_rendering_driver_name(); 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, init_embed_parent_window_id, err); if (err != OK || display_server == nullptr) { @@ -3862,10 +3868,6 @@ void Main::setup_boot_logo() { GLOBAL_GET("rendering/environment/defaults/default_clear_color")); } -String Main::get_rendering_driver_name() { - return rendering_driver; -} - String Main::get_locale_override() { return locale; } diff --git a/main/main.h b/main/main.h index 653461ea56..53a7b69733 100644 --- a/main/main.h +++ b/main/main.h @@ -71,7 +71,6 @@ public: static int test_entrypoint(int argc, char *argv[], bool &tests_need_run); static Error setup(const char *execpath, int argc, char *argv[], bool p_second_phase = true); static Error setup2(bool p_show_boot_logo = true); // The thread calling setup2() will effectively become the main thread. - static String get_rendering_driver_name(); static String get_locale_override(); static void setup_boot_logo(); #ifdef TESTS_ENABLED diff --git a/modules/openxr/register_types.cpp b/modules/openxr/register_types.cpp index 0b73fcd604..812b656add 100644 --- a/modules/openxr/register_types.cpp +++ b/modules/openxr/register_types.cpp @@ -237,7 +237,7 @@ void initialize_openxr_module(ModuleInitializationLevel p_level) { openxr_api = memnew(OpenXRAPI); ERR_FAIL_NULL(openxr_api); - if (!openxr_api->initialize(Main::get_rendering_driver_name())) { + if (!openxr_api->initialize(OS::get_singleton()->get_current_rendering_driver_name())) { const char *init_error_message = "OpenXR was requested but failed to start.\n" "HMD was not detected or a required feature was not supported.\n\n" diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index 70e2b2f838..1ab18e7853 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -52,6 +52,11 @@ #include #endif +#if defined(RD_ENABLED) +static RenderingContextDriver *rendering_context_global = nullptr; +static bool rendering_context_global_checked = false; +#endif + DisplayServerAndroid *DisplayServerAndroid::get_singleton() { return static_cast(DisplayServer::get_singleton()); } @@ -671,15 +676,57 @@ void DisplayServerAndroid::register_android_driver() { register_create_function("android", create_func, get_rendering_drivers_func); } +#ifdef VULKAN_ENABLED +bool DisplayServerAndroid::check_vulkan_global_context(bool p_vulkan_requirements_met) { + if (!rendering_context_global_checked) { + bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3"); + Error err = ERR_CANT_CREATE; + if (p_vulkan_requirements_met) { + rendering_context_global = memnew(RenderingContextDriverVulkanAndroid); + err = rendering_context_global->initialize(); + } + + if (err != OK) { + if (rendering_context_global != nullptr) { + memdelete(rendering_context_global); + rendering_context_global = nullptr; + } + +#if defined(GLES3_ENABLED) + if (fallback_to_opengl3) { + WARN_PRINT("Your device does not seem to support Vulkan, switching to OpenGL 3."); + OS::get_singleton()->set_current_rendering_driver_name("opengl3", OS::RENDERING_SOURCE_FALLBACK); + OS::get_singleton()->set_current_rendering_method("gl_compatibility", OS::RENDERING_SOURCE_FALLBACK); + } else +#endif + { + ERR_PRINT("Failed to initialize Vulkan context."); + } + } + + rendering_context_global_checked = true; + } + + return rendering_context_global != nullptr; +} + +void DisplayServerAndroid::free_vulkan_global_context() { + if (rendering_context_global != nullptr) { + memdelete(rendering_context_global); + rendering_context_global = nullptr; + } +} +#endif + void DisplayServerAndroid::reset_window() { #if defined(RD_ENABLED) - if (rendering_context) { + if (rendering_context_global) { if (rendering_device) { rendering_device->screen_free(MAIN_WINDOW_ID); } - VSyncMode last_vsync_mode = rendering_context->window_get_vsync_mode(MAIN_WINDOW_ID); - rendering_context->window_destroy(MAIN_WINDOW_ID); + VSyncMode last_vsync_mode = rendering_context_global->window_get_vsync_mode(MAIN_WINDOW_ID); + rendering_context_global->window_destroy(MAIN_WINDOW_ID); union { #ifdef VULKAN_ENABLED @@ -694,16 +741,14 @@ void DisplayServerAndroid::reset_window() { } #endif - if (rendering_context->window_create(MAIN_WINDOW_ID, &wpd) != OK) { + if (rendering_context_global->window_create(MAIN_WINDOW_ID, &wpd) != OK) { ERR_PRINT(vformat("Failed to reset %s window.", rendering_driver)); - memdelete(rendering_context); - rendering_context = nullptr; return; } Size2i display_size = OS_Android::get_singleton()->get_display_size(); - rendering_context->window_set_size(MAIN_WINDOW_ID, display_size.width, display_size.height); - rendering_context->window_set_vsync_mode(MAIN_WINDOW_ID, last_vsync_mode); + rendering_context_global->window_set_size(MAIN_WINDOW_ID, display_size.width, display_size.height); + rendering_context_global->window_set_vsync_mode(MAIN_WINDOW_ID, last_vsync_mode); if (rendering_device) { rendering_device->screen_create(MAIN_WINDOW_ID); @@ -733,71 +778,37 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis native_menu = memnew(NativeMenu); -#if defined(RD_ENABLED) - rendering_context = nullptr; - rendering_device = nullptr; - -#if defined(VULKAN_ENABLED) +#ifdef VULKAN_ENABLED if (rendering_driver == "vulkan") { - rendering_context = memnew(RenderingContextDriverVulkanAndroid); - } -#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 does not seem 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_global == nullptr) { + ERR_PRINT("Can't initialize display server with Vulkan driver because no Vulkan context is available."); + r_error = ERR_UNAVAILABLE; + return; } - } - if (rendering_context) { - union { -#ifdef VULKAN_ENABLED - RenderingContextDriverVulkanAndroid::WindowPlatformData vulkan; -#endif - } wpd; -#ifdef VULKAN_ENABLED - if (rendering_driver == "vulkan") { - ANativeWindow *native_window = OS_Android::get_singleton()->get_native_window(); - ERR_FAIL_NULL(native_window); - wpd.vulkan.window = native_window; - } -#endif + ANativeWindow *native_window = OS_Android::get_singleton()->get_native_window(); + ERR_FAIL_NULL(native_window); - if (rendering_context->window_create(MAIN_WINDOW_ID, &wpd) != OK) { + RenderingContextDriverVulkanAndroid::WindowPlatformData wpd; + wpd.window = native_window; + + if (rendering_context_global->window_create(MAIN_WINDOW_ID, &wpd) != OK) { ERR_PRINT(vformat("Failed to create %s window.", rendering_driver)); - memdelete(rendering_context); - rendering_context = nullptr; r_error = ERR_UNAVAILABLE; return; } Size2i display_size = OS_Android::get_singleton()->get_display_size(); - rendering_context->window_set_size(MAIN_WINDOW_ID, display_size.width, display_size.height); - rendering_context->window_set_vsync_mode(MAIN_WINDOW_ID, p_vsync_mode); + rendering_context_global->window_set_size(MAIN_WINDOW_ID, display_size.width, display_size.height); + rendering_context_global->window_set_vsync_mode(MAIN_WINDOW_ID, p_vsync_mode); rendering_device = memnew(RenderingDevice); - if (rendering_device->initialize(rendering_context, MAIN_WINDOW_ID) != OK) { + if (rendering_device->initialize(rendering_context_global, MAIN_WINDOW_ID) != OK) { rendering_device = nullptr; - memdelete(rendering_context); - rendering_context = nullptr; r_error = ERR_UNAVAILABLE; return; } + rendering_device->screen_create(MAIN_WINDOW_ID); RendererCompositorRD::make_current(); @@ -825,9 +836,8 @@ DisplayServerAndroid::~DisplayServerAndroid() { if (rendering_device) { memdelete(rendering_device); } - if (rendering_context) { - memdelete(rendering_context); - } + + free_vulkan_global_context(); #endif } @@ -953,16 +963,16 @@ void DisplayServerAndroid::cursor_set_custom_image(const Ref &p_cursor void DisplayServerAndroid::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) { #if defined(RD_ENABLED) - if (rendering_context) { - rendering_context->window_set_vsync_mode(p_window, p_vsync_mode); + if (rendering_context_global) { + rendering_context_global->window_set_vsync_mode(p_window, p_vsync_mode); } #endif } DisplayServer::VSyncMode DisplayServerAndroid::window_get_vsync_mode(WindowID p_window) const { #if defined(RD_ENABLED) - if (rendering_context) { - return rendering_context->window_get_vsync_mode(p_window); + if (rendering_context_global) { + return rendering_context_global->window_get_vsync_mode(p_window); } #endif return DisplayServer::VSYNC_ENABLED; diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h index 49301d4b7f..1299ec9048 100644 --- a/platform/android/display_server_android.h +++ b/platform/android/display_server_android.h @@ -76,7 +76,6 @@ class DisplayServerAndroid : public DisplayServer { CursorShape cursor_shape = CursorShape::CURSOR_ARROW; #if defined(RD_ENABLED) - RenderingContextDriver *rendering_context = nullptr; RenderingDevice *rendering_device = nullptr; #endif NativeMenu *native_menu = nullptr; @@ -246,6 +245,11 @@ public: static Vector get_rendering_drivers_func(); static void register_android_driver(); +#ifdef VULKAN_ENABLED + static bool check_vulkan_global_context(bool p_vulkan_requirements_met); + static void free_vulkan_global_context(); +#endif + void reset_window(); void notify_surface_changed(int p_width, int p_height); void notify_application_paused(); diff --git a/platform/android/java/lib/src/main/java/org/godotengine/godot/Godot.kt b/platform/android/java/lib/src/main/java/org/godotengine/godot/Godot.kt index a1bfbcb9a2..4b3eb0e8d0 100644 --- a/platform/android/java/lib/src/main/java/org/godotengine/godot/Godot.kt +++ b/platform/android/java/lib/src/main/java/org/godotengine/godot/Godot.kt @@ -565,19 +565,14 @@ class Godot private constructor(val context: Context) { !isEditorHint() && java.lang.Boolean.parseBoolean(GodotLib.getGlobal("display/window/per_pixel_transparency/allowed")) Log.d(TAG, "Render view should be transparent: $shouldBeTransparent") - renderView = if (usesVulkan()) { - if (meetsVulkanRequirements(context.packageManager)) { - GodotVulkanRenderView(this, godotInputHandler, shouldBeTransparent) - } else if (canFallbackToOpenGL()) { - // Fallback to OpenGl. - GodotGLRenderView(this, godotInputHandler, xrMode, useDebugOpengl, shouldBeTransparent) - } else { - throw IllegalStateException(context.getString(R.string.error_missing_vulkan_requirements_message)) - } + val nativeRenderer = getNativeRenderer(); + if (nativeRenderer == "vulkan") { + renderView = GodotVulkanRenderView(this, godotInputHandler, shouldBeTransparent) + } else if (nativeRenderer == "opengl3") { + renderView = GodotGLRenderView(this, godotInputHandler, xrMode, useDebugOpengl, shouldBeTransparent) } else { - // Fallback to OpenGl. - GodotGLRenderView(this, godotInputHandler, xrMode, useDebugOpengl, shouldBeTransparent) + throw IllegalStateException("No native renderer is available.") } renderView?.let { @@ -934,31 +929,25 @@ class Godot private constructor(val context: Context) { */ private fun isOnUiThread() = Looper.myLooper() == Looper.getMainLooper() - /** - * Returns true if `Vulkan` is used for rendering. +/** + * Returns the native rendering driver. */ - private fun usesVulkan(): Boolean { - val rendererInfo = GodotLib.getRendererInfo() - var renderingDeviceSource = "ProjectSettings" - var renderingDevice = rendererInfo[0] - var rendererSource = "ProjectSettings" - var renderer = rendererInfo[1] - val cmdline = commandLine - var index = cmdline.indexOf("--rendering-method") - if (index > -1 && cmdline.size > index + 1) { - rendererSource = "CommandLine" - renderer = cmdline.get(index + 1) + private fun getNativeRenderer(): String { + val rendererInfo = GodotLib.getRendererInfo(meetsVulkanRequirements(context.packageManager)) + var renderingDriverChosen = rendererInfo[0] + var renderingDriverOriginal = rendererInfo[1] + var renderingMethod = rendererInfo[2] + var renderingDriverSource = rendererInfo[3] + var renderingMethodSource = rendererInfo[4] + Log.d(TAG, """renderingDevice: ${renderingDriverChosen} (${renderingDriverSource}) + renderer: ${renderingMethod} (${renderingMethodSource})""") + + if (renderingDriverOriginal == "vulkan" && renderingDriverChosen == "") { + // Throw the exception for the case where Vulkan failed to create and no fallback was available. + throw IllegalStateException(context.getString(R.string.error_missing_vulkan_requirements_message)) } - index = cmdline.indexOf("--rendering-driver") - if (index > -1 && cmdline.size > index + 1) { - renderingDeviceSource = "CommandLine" - renderingDevice = cmdline.get(index + 1) - } - val result = ("forward_plus" == renderer || "mobile" == renderer) && "vulkan" == renderingDevice - Log.d(TAG, """usesVulkan(): ${result} - renderingDevice: ${renderingDevice} (${renderingDeviceSource}) - renderer: ${renderer} (${rendererSource})""") - return result + + return renderingDriverChosen; } /** diff --git a/platform/android/java/lib/src/main/java/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/main/java/org/godotengine/godot/GodotLib.java index 38e32714cf..dad17bfc90 100644 --- a/platform/android/java/lib/src/main/java/org/godotengine/godot/GodotLib.java +++ b/platform/android/java/lib/src/main/java/org/godotengine/godot/GodotLib.java @@ -192,11 +192,14 @@ public class GodotLib { /** * Used to get info about the current rendering system. * - * @return A String array with two elements: - * [0] Rendering driver name. - * [1] Rendering method. + * @return A String array with three elements: + * [0] Rendering driver name chosen for rendering. + * [1] Rendering driver name chosen before any fallbacks were applied. + * [2] Rendering method. + * [3] Source where the rendering driver was chosen from. + * [4] Source where the rendering method was chosen from. */ - public static native String[] getRendererInfo(); + public static native String[] getRendererInfo(boolean p_vulkan_requirements_met); /** * Used to access Godot's editor settings. diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index 41f963849a..541a3a15d1 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -139,6 +139,21 @@ static void _terminate(JNIEnv *env, bool p_restart = false) { } } +static String rendering_source_to_string(OS::RenderingSource p_source) { + switch (p_source) { + case OS::RENDERING_SOURCE_DEFAULT: + return "Default"; + case OS::RENDERING_SOURCE_PROJECT_SETTING: + return "ProjectSettings"; + case OS::RENDERING_SOURCE_COMMANDLINE: + return "Commandline"; + case OS::RENDERING_SOURCE_FALLBACK: + return "Fallback"; + default: + return "Unknown"; + } +} + extern "C" { JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHeight(JNIEnv *env, jclass clazz, jint p_height) { @@ -487,13 +502,30 @@ JNIEXPORT jstring JNICALL Java_org_godotengine_godot_GodotLib_getGlobal(JNIEnv * return env->NewStringUTF(setting_value.utf8().get_data()); } -JNIEXPORT jobjectArray JNICALL Java_org_godotengine_godot_GodotLib_getRendererInfo(JNIEnv *env, jclass clazz) { - String rendering_driver = RenderingServer::get_singleton()->get_current_rendering_driver_name(); +JNIEXPORT jobjectArray JNICALL Java_org_godotengine_godot_GodotLib_getRendererInfo(JNIEnv *env, jclass clazz, jboolean p_vulkan_requirements_met) { + String rendering_driver_original = RenderingServer::get_singleton()->get_current_rendering_driver_name(); + String rendering_driver_chosen = rendering_driver_original; String rendering_method = RenderingServer::get_singleton()->get_current_rendering_method(); - jobjectArray result = env->NewObjectArray(2, jni_find_class(env, "java/lang/String"), nullptr); - env->SetObjectArrayElement(result, 0, env->NewStringUTF(rendering_driver.utf8().get_data())); - env->SetObjectArrayElement(result, 1, env->NewStringUTF(rendering_method.utf8().get_data())); +#ifdef VULKAN_ENABLED + if (rendering_driver_original == "vulkan" && !DisplayServerAndroid::check_vulkan_global_context(p_vulkan_requirements_met)) { + // The Android display server only gets created after this step, so a static check must be used to check for Vulkan + // availability instead. If the check fails, it'll fall back to OpenGL3 accordingly if the relevant project setting + // is enabled. The Vulkan context created by this check will be reused by the DisplayServer afterwards. + rendering_driver_chosen = RenderingServer::get_singleton()->get_current_rendering_driver_name(); + rendering_method = RenderingServer::get_singleton()->get_current_rendering_method(); + } +#endif + + String rendering_driver_source = rendering_source_to_string(OS::get_singleton()->get_current_rendering_driver_name_source()); + String rendering_method_source = rendering_source_to_string(OS::get_singleton()->get_current_rendering_method_source()); + + jobjectArray result = env->NewObjectArray(5, jni_find_class(env, "java/lang/String"), nullptr); + env->SetObjectArrayElement(result, 0, env->NewStringUTF(rendering_driver_chosen.utf8().get_data())); + env->SetObjectArrayElement(result, 1, env->NewStringUTF(rendering_driver_original.utf8().get_data())); + env->SetObjectArrayElement(result, 2, env->NewStringUTF(rendering_method.utf8().get_data())); + env->SetObjectArrayElement(result, 3, env->NewStringUTF(rendering_driver_source.utf8().get_data())); + env->SetObjectArrayElement(result, 4, env->NewStringUTF(rendering_method_source.utf8().get_data())); return result; } diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h index 0df2079416..4215053ea8 100644 --- a/platform/android/java_godot_lib_jni.h +++ b/platform/android/java_godot_lib_jni.h @@ -60,7 +60,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_gyroscope(JNIEnv *env JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusin(JNIEnv *env, jclass clazz); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusout(JNIEnv *env, jclass clazz); JNIEXPORT jstring JNICALL Java_org_godotengine_godot_GodotLib_getGlobal(JNIEnv *env, jclass clazz, jstring path); -JNIEXPORT jobjectArray JNICALL Java_org_godotengine_godot_GodotLib_getRendererInfo(JNIEnv *env, jclass clazz); +JNIEXPORT jobjectArray JNICALL Java_org_godotengine_godot_GodotLib_getRendererInfo(JNIEnv *env, jclass clazz, jboolean p_vulkan_requirements_met); JNIEXPORT jstring JNICALL Java_org_godotengine_godot_GodotLib_getEditorSetting(JNIEnv *env, jclass clazz, jstring p_setting_key); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setEditorSetting(JNIEnv *env, jclass clazz, jstring p_key, jobject p_data); JNIEXPORT jobject JNICALL Java_org_godotengine_godot_GodotLib_getEditorProjectMetadata(JNIEnv *env, jclass clazz, jstring p_section, jstring p_key, jobject p_default_value); diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp index 6cdf0dd9b0..74c02c691c 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.cpp +++ b/platform/linuxbsd/wayland/display_server_wayland.cpp @@ -2079,8 +2079,8 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win 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); + OS::get_singleton()->set_current_rendering_method("gl_compatibility", OS::RENDERING_SOURCE_FALLBACK); + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver, OS::RENDERING_SOURCE_FALLBACK); } else #endif // GLES3_ENABLED { @@ -2167,7 +2167,7 @@ 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); + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver, OS::RENDERING_SOURCE_FALLBACK); } else { r_error = ERR_UNAVAILABLE; diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index 9c8e0536d7..a3d6f53c34 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -7045,8 +7045,8 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode 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); + OS::get_singleton()->set_current_rendering_method("gl_compatibility", OS::RENDERING_SOURCE_FALLBACK); + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver, OS::RENDERING_SOURCE_FALLBACK); } else #endif // GLES3_ENABLED { @@ -7122,7 +7122,7 @@ 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); + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver, OS::RENDERING_SOURCE_FALLBACK); } else { r_error = ERR_UNAVAILABLE; diff --git a/platform/macos/display_server_embedded.mm b/platform/macos/display_server_embedded.mm index ce20831426..d0c9c6ab0e 100644 --- a/platform/macos/display_server_embedded.mm +++ b/platform/macos/display_server_embedded.mm @@ -78,7 +78,7 @@ DisplayServerEmbedded::DisplayServerEmbedded(const String &p_rendering_driver, W // Metal rendering driver not available on Intel. if (rendering_driver == "metal") { rendering_driver = "vulkan"; - OS::get_singleton()->set_current_rendering_driver_name(rendering_driver); + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver, OS::RENDERING_SOURCE_FALLBACK); } #endif if (rendering_driver == "vulkan") { @@ -100,8 +100,8 @@ DisplayServerEmbedded::DisplayServerEmbedded(const String &p_rendering_driver, W if (fallback_to_opengl3 && rendering_driver != "opengl3") { WARN_PRINT("Your device does not seem 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); + OS::get_singleton()->set_current_rendering_method("gl_compatibility", OS::RENDERING_SOURCE_FALLBACK); + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver, OS::RENDERING_SOURCE_FALLBACK); } else #endif { @@ -116,7 +116,7 @@ DisplayServerEmbedded::DisplayServerEmbedded(const String &p_rendering_driver, W if (rendering_driver == "opengl3_angle") { WARN_PRINT("ANGLE not supported for embedded display, switching to native OpenGL."); rendering_driver = "opengl3"; - OS::get_singleton()->set_current_rendering_driver_name(rendering_driver); + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver, OS::RENDERING_SOURCE_FALLBACK); } if (rendering_driver == "opengl3") { diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index fd076a4711..630acf4b61 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -3808,7 +3808,7 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM // Metal rendering driver not available on Intel. if (rendering_driver == "metal") { rendering_driver = "vulkan"; - OS::get_singleton()->set_current_rendering_driver_name(rendering_driver); + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver, OS::RENDERING_SOURCE_FALLBACK); } #endif if (rendering_driver == "vulkan") { @@ -3830,8 +3830,8 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM if (fallback_to_opengl3 && rendering_driver != "opengl3") { WARN_PRINT("Your device does not seem 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); + OS::get_singleton()->set_current_rendering_method("gl_compatibility", OS::RENDERING_SOURCE_FALLBACK); + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver, OS::RENDERING_SOURCE_FALLBACK); } else #endif { @@ -3856,7 +3856,7 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM 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); + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver, OS::RENDERING_SOURCE_FALLBACK); } else { r_error = ERR_UNAVAILABLE; ERR_FAIL_MSG("Could not initialize ANGLE OpenGL."); diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 6d69e658be..6e0d1837fb 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -7310,7 +7310,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win } #endif rendering_driver = tested_rendering_driver; - OS::get_singleton()->set_current_rendering_driver_name(rendering_driver); + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver, i > 0 ? OS::RENDERING_SOURCE_FALLBACK : OS::get_singleton()->get_current_rendering_driver_name_source()); break; } @@ -7336,8 +7336,8 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win 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); + OS::get_singleton()->set_current_rendering_method("gl_compatibility", OS::RENDERING_SOURCE_FALLBACK); + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver, OS::RENDERING_SOURCE_FALLBACK); rendering_driver_failed = false; } } @@ -7419,7 +7419,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win } } rendering_driver = "opengl3_angle"; - OS::get_singleton()->set_current_rendering_driver_name(rendering_driver); + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver, OS::RENDERING_SOURCE_FALLBACK); } }