Add Swappy & Pre-Transformed 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.
This commit is contained in:
Matias N. Goldberg
2024-05-05 19:15:56 -03:00
parent 92e51fca72
commit aaa0e2fddf
23 changed files with 1064 additions and 14 deletions
@@ -66,6 +66,16 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_target_descriptors[rd_texture], 0);
// We need to invert the phone rotation.
int screen_rotation_degrees = -DisplayServer::get_singleton()->screen_get_internal_current_rotation();
float screen_rotation = Math::deg_to_rad((float)screen_rotation_degrees);
blit.push_constant.rotation_cos = Math::cos(screen_rotation);
blit.push_constant.rotation_sin = Math::sin(screen_rotation);
// Swap width and height when the orientation is not the native one.
if (screen_rotation_degrees % 180 != 0) {
SWAP(screen_size.width, screen_size.height);
}
blit.push_constant.src_rect[0] = p_render_targets[i].src_rect.position.x;
blit.push_constant.src_rect[1] = p_render_targets[i].src_rect.position.y;
blit.push_constant.src_rect[2] = p_render_targets[i].src_rect.size.width;
@@ -228,6 +238,10 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uset, 0);
int screen_rotation_degrees = DisplayServer::get_singleton()->screen_get_internal_current_rotation();
float screen_rotation = Math::deg_to_rad((float)screen_rotation_degrees);
blit.push_constant.rotation_cos = Math::cos(screen_rotation);
blit.push_constant.rotation_sin = Math::sin(screen_rotation);
blit.push_constant.src_rect[0] = 0.0;
blit.push_constant.src_rect[1] = 0.0;
blit.push_constant.src_rect[2] = 1.0;