Fixes an issue introduced in #96439 (see
https://github.com/godotengine/godot/pull/96439#issuecomment-2447288702)
Godot was relying on Java's
activity.getWindowManager().getDefaultDisplay().getRotation(); to apply
pre-rotation but this is wrong.
First, getRotation() may temporarily return a different value from the
correct one; which is what was causing the splash screen to be upside
down. It would return -90 instead of 90 for the first rendered frame.
But unfortunately, the splash screen is just one frame rendered for a
very long time, so the error lingered for a long time for everyone to
see.
Second, to determine what rotation to use, we should be looking at what
Vulkan told us, which is the value we pass to
VkSurfaceTransformFlagBitsKHR::preTransform.
This commit removes the now-unnecessary
screen_get_internal_current_rotation() function (which was introduced by
#96439) and now saves the preTransform value in the swapchain.
- Adds Swappy for Android for stable frame pacing
- Implements pre-transformed Swapchain so that Godot's compositor is in
charge of rotating the screen instead of Android's compositor
(performance optimization for phones that don't have HW rotator)
============================
The work was performed by collaboration of TheForge and Google. I am
merely splitting it up into smaller PRs and cleaning it up.
Changes from original PR:
- Removed "display/window/frame_pacing/android/target_frame_rate" option
to use Engine::get_max_fps instead.
- Target framerate can be changed at runtime using Engine::set_max_fps.
- Swappy is enabled by default.
- Added documentation.
- enable_auto_swap setting is replaced with swappy_mode.
Thanks for the fix of `JavaClassWrapper` in https://github.com/godotengine/godot/pull/96182 and the changes in the previous commit, this introduces an `AndroidRuntime` plugin which provides GDScript access to the Android runtime capabilities.
This allows developers to get access to various Android capabilities without the need of a plugin.
For example, the following logic can be used to check whether the device supports vibration:
```
var android_runtime = Engine.get_singleton("AndroidRuntime")
if android_runtime:
print("Checking if the device supports vibration")
var vibrator_service = android_runtime.getApplicationContext().getSystemService("vibrator")
if vibrator_service:
if vibrator_service.hasVibrator():
print("Vibration is supported on device!")
else:
printerr("Vibration is not supported on device")
else:
printerr("Unable to retrieve the vibrator service")
else:
printerr("Couldn't find AndroidRuntime singleton")
```
A few permissions including the `USE_SCENE` permission are being renamed with the launch of the Meta Spatial SDK, so we update the excluded list to avoid requesting them on app start.
Some platforms don't support hostfxr but we can use the coreclr/monosgen library directly to initialize the runtime.
Android exports now use the `android` runtime identifier instead of `linux-bionic`, this removes the restrictions we previously had:
- Adds support for all Android architectures (arm32, arm64, x32, and x64), previously only the 64-bit architectures were supported.
- Loads `System.Security.Cryptography.Native.Android` (the .NET library that binds to the Android OS crypto functions).
Update the export logic to enable apk generation and signing for Android editor builds
Note: Only legacy builds are supported. Gradle builds are not supported at this point in time.
- Returns an empty list when there's not registered plugins, thus preventing the creation of spurious iterator objects
- Inline `Godot#getRotatedValues(...)` given it only had a single caller. This allows to remove the allocation of a float array on each call and replace it with float variables
- Disable sensor events by default. Sensor events can fired at 10-100s Hz taking cpu and memory resources. Now the use of sensor data is behind a project setting allowing projects that have use of it to enable it, while other projects don't pay the cost for a feature they don't use
- Create a pool of specialized input `Runnable` objects to prevent spurious, unbounded `Runnable` allocations
- Disable showing the boot logo for Android XR projects
- Delete locale references of jni strings
On Android the exit logic goes through `Godot#onDestroy()` who attempts to cleanup the engine using the following code:
```
runOnRenderThread {
GodotLib.ondestroy()
forceQuit()
}
```
The issue however is that by the time we ran this code, the render thread has already been paused (but not yet destroyed), and thus `GodotLib.ondestroy()` and `forceQuit()` which are scheduled on the render thread are not executed.
To address this, we instead explicitly request the render thread to exit and block until it does. As part of it exit logic, the render thread has been updated to properly destroy and clean the native instance of the Godot engine, resolving the issue.
Long press is used to simulate right-click events for finger touch and stylus. The previous logic also caused it to trigger for mouse input, which is not needed since the user can instead use the mouse right click button.
This update disables long press as right click events for mouse input.
- Add support for dispatching input on the render thread (UI thread is the current default) when `input_buffering` and `accumulated_input` are disabled. At the expense of latency, this helps prevent 'heavy' applications / games from blocking the UI thread (the default behavior) which may cause the application to ANR.
- Remove GLSurfaceView logic causing the UI thread to wait on the GL thread during lifecycle events. The removed logic would cause the UI thread to ANR when the GL thread is blocked.