Skip to content

Commit 322ff4d

Browse files
darksylincWhalesState
authored andcommitted
Fix splash screen upside down on Android
Fixes an issue introduced in godotengine#96439 (see godotengine#96439 (comment)) 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 godotengine#96439) and now saves the preTransform value in the swapchain.
1 parent 3999485 commit 322ff4d

12 files changed

+42
-53
lines changed

drivers/vulkan/rendering_device_driver_vulkan.cpp

+25
Original file line numberDiff line numberDiff line change
@@ -2795,6 +2795,24 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue,
27952795
swap_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
27962796
swap_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
27972797
swap_create_info.preTransform = surface_transform_bits;
2798+
switch (swap_create_info.preTransform) {
2799+
case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
2800+
swap_chain->pre_transform_rotation_degrees = 0;
2801+
break;
2802+
case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
2803+
swap_chain->pre_transform_rotation_degrees = 90;
2804+
break;
2805+
case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
2806+
swap_chain->pre_transform_rotation_degrees = 180;
2807+
break;
2808+
case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
2809+
swap_chain->pre_transform_rotation_degrees = 270;
2810+
break;
2811+
default:
2812+
WARN_PRINT("Unexpected swap_create_info.preTransform = " + itos(swap_create_info.preTransform) + ".");
2813+
swap_chain->pre_transform_rotation_degrees = 0;
2814+
break;
2815+
}
27982816
swap_create_info.compositeAlpha = composite_alpha;
27992817
swap_create_info.presentMode = present_mode;
28002818
swap_create_info.clipped = true;
@@ -2959,6 +2977,13 @@ RDD::RenderPassID RenderingDeviceDriverVulkan::swap_chain_get_render_pass(SwapCh
29592977
return swap_chain->render_pass;
29602978
}
29612979

2980+
int RenderingDeviceDriverVulkan::swap_chain_get_pre_rotation_degrees(SwapChainID p_swap_chain) {
2981+
DEV_ASSERT(p_swap_chain.id != 0);
2982+
2983+
SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);
2984+
return swap_chain->pre_transform_rotation_degrees;
2985+
}
2986+
29622987
RDD::DataFormat RenderingDeviceDriverVulkan::swap_chain_get_format(SwapChainID p_swap_chain) {
29632988
DEV_ASSERT(p_swap_chain.id != 0);
29642989

drivers/vulkan/rendering_device_driver_vulkan.h

+2
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
337337
LocalVector<CommandQueue *> command_queues_acquired;
338338
LocalVector<uint32_t> command_queues_acquired_semaphores;
339339
RenderPassID render_pass;
340+
int pre_transform_rotation_degrees = 0;
340341
uint32_t image_index = 0;
341342
#ifdef ANDROID_ENABLED
342343
uint64_t refresh_duration = 0;
@@ -351,6 +352,7 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
351352
virtual Error swap_chain_resize(CommandQueueID p_cmd_queue, SwapChainID p_swap_chain, uint32_t p_desired_framebuffer_count) override final;
352353
virtual FramebufferID swap_chain_acquire_framebuffer(CommandQueueID p_cmd_queue, SwapChainID p_swap_chain, bool &r_resize_required) override final;
353354
virtual RenderPassID swap_chain_get_render_pass(SwapChainID p_swap_chain) override final;
355+
virtual int swap_chain_get_pre_rotation_degrees(SwapChainID p_swap_chain) override final;
354356
virtual DataFormat swap_chain_get_format(SwapChainID p_swap_chain) override final;
355357
virtual void swap_chain_set_max_fps(SwapChainID p_swap_chain, int p_max_fps) override final;
356358
virtual void swap_chain_free(SwapChainID p_swap_chain) override final;

platform/android/display_server_android.cpp

-8
Original file line numberDiff line numberDiff line change
@@ -216,14 +216,6 @@ DisplayServer::ScreenOrientation DisplayServerAndroid::screen_get_orientation(in
216216
return (ScreenOrientation)orientation;
217217
}
218218

219-
int DisplayServerAndroid::screen_get_internal_current_rotation(int p_screen) const {
220-
GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();
221-
ERR_FAIL_NULL_V(godot_io_java, 0);
222-
223-
const int rotation = godot_io_java->get_internal_current_screen_rotation();
224-
return rotation;
225-
}
226-
227219
int DisplayServerAndroid::get_screen_count() const {
228220
return 1;
229221
}

platform/android/display_server_android.h

-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ class DisplayServerAndroid : public DisplayServer {
124124

125125
virtual void screen_set_orientation(ScreenOrientation p_orientation, int p_screen = SCREEN_OF_MAIN_WINDOW) override;
126126
virtual ScreenOrientation screen_get_orientation(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
127-
virtual int screen_get_internal_current_rotation(int p_screen) const override;
128127

129128
virtual int get_screen_count() const override;
130129
virtual int get_primary_screen() const override;

platform/android/java/lib/src/org/godotengine/godot/GodotIO.java

-22
Original file line numberDiff line numberDiff line change
@@ -296,28 +296,6 @@ public int getScreenOrientation() {
296296
}
297297
}
298298

299-
/**
300-
This function is used by DisplayServer::screen_get_internal_current_rotation (C++)
301-
and is used to implement a performance optimization in devices that do not offer
302-
a HW rotator.
303-
@return
304-
Rotation in degrees, in multiples of 90°
305-
*/
306-
public int getInternalCurrentScreenRotation() {
307-
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
308-
309-
switch (rotation) {
310-
case Surface.ROTATION_90:
311-
return 90;
312-
case Surface.ROTATION_180:
313-
return 180;
314-
case Surface.ROTATION_270:
315-
return 270;
316-
default:
317-
return 0;
318-
}
319-
}
320-
321299
public void setEdit(GodotEditText _edit) {
322300
edit = _edit;
323301
}

platform/android/java_godot_io_wrapper.cpp

-11
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc
6666
_has_hardware_keyboard = p_env->GetMethodID(cls, "hasHardwareKeyboard", "()Z");
6767
_set_screen_orientation = p_env->GetMethodID(cls, "setScreenOrientation", "(I)V");
6868
_get_screen_orientation = p_env->GetMethodID(cls, "getScreenOrientation", "()I");
69-
_get_internal_current_screen_rotation = p_env->GetMethodID(cls, "getInternalCurrentScreenRotation", "()I");
7069
_get_system_dir = p_env->GetMethodID(cls, "getSystemDir", "(IZ)Ljava/lang/String;");
7170
}
7271
}
@@ -268,16 +267,6 @@ int GodotIOJavaWrapper::get_screen_orientation() {
268267
}
269268
}
270269

271-
int GodotIOJavaWrapper::get_internal_current_screen_rotation() {
272-
if (_get_internal_current_screen_rotation) {
273-
JNIEnv *env = get_jni_env();
274-
ERR_FAIL_NULL_V(env, 0);
275-
return env->CallIntMethod(godot_io_instance, _get_internal_current_screen_rotation);
276-
} else {
277-
return 0;
278-
}
279-
}
280-
281270
String GodotIOJavaWrapper::get_system_dir(int p_dir, bool p_shared_storage) {
282271
if (_get_system_dir) {
283272
JNIEnv *env = get_jni_env();

platform/android/java_godot_io_wrapper.h

-2
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ class GodotIOJavaWrapper {
6161
jmethodID _has_hardware_keyboard = 0;
6262
jmethodID _set_screen_orientation = 0;
6363
jmethodID _get_screen_orientation = 0;
64-
jmethodID _get_internal_current_screen_rotation = 0;
6564
jmethodID _get_system_dir = 0;
6665

6766
public:
@@ -89,7 +88,6 @@ class GodotIOJavaWrapper {
8988
void set_vk_height(int p_height);
9089
void set_screen_orientation(int p_orient);
9190
int get_screen_orientation();
92-
int get_internal_current_screen_rotation();
9391
String get_system_dir(int p_dir, bool p_shared_storage);
9492
};
9593

servers/display_server.h

-7
Original file line numberDiff line numberDiff line change
@@ -360,13 +360,6 @@ class DisplayServer : public Object {
360360

361361
virtual void screen_set_orientation(ScreenOrientation p_orientation, int p_screen = SCREEN_OF_MAIN_WINDOW);
362362
virtual ScreenOrientation screen_get_orientation(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
363-
// Note: The "internal" current orientation is not necessarily the current orientation and will often be 0 for most platforms.
364-
//
365-
// Some Android GPUs come with a HW-based rotator which means the screen gets rotated for free to
366-
// whatever orientation the device is currently facing. But many Android GPUs emulate it via SW instead,
367-
// which costs performance and power. This value is an optimization that tells Godot's compositor how to
368-
// rotate the render texture before presenting to screen so that Android's compositor doesn't have to.
369-
virtual int screen_get_internal_current_rotation(int p_screen = SCREEN_OF_MAIN_WINDOW) const { return 0; }
370363

371364
virtual void screen_set_keep_on(bool p_enable); //disable screensaver
372365
virtual bool screen_is_kept_on() const;

servers/rendering/renderer_rd/renderer_compositor_rd.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
6767
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_target_descriptors[rd_texture], 0);
6868

6969
// We need to invert the phone rotation.
70-
int screen_rotation_degrees = -DisplayServer::get_singleton()->screen_get_internal_current_rotation();
70+
const int screen_rotation_degrees = -RD::get_singleton()->screen_get_pre_rotation_degrees(p_screen);
7171
float screen_rotation = Math::deg_to_rad((float)screen_rotation_degrees);
7272

7373
blit.push_constant.rotation_cos = Math::cos(screen_rotation);
@@ -238,7 +238,7 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
238238
RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array);
239239
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uset, 0);
240240

241-
int screen_rotation_degrees = DisplayServer::get_singleton()->screen_get_internal_current_rotation();
241+
const int screen_rotation_degrees = -RD::get_singleton()->screen_get_pre_rotation_degrees(DisplayServer::MAIN_WINDOW_ID);
242242
float screen_rotation = Math::deg_to_rad((float)screen_rotation_degrees);
243243
blit.push_constant.rotation_cos = Math::cos(screen_rotation);
244244
blit.push_constant.rotation_sin = Math::sin(screen_rotation);

servers/rendering/rendering_device.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -3511,6 +3511,15 @@ int RenderingDevice::screen_get_height(DisplayServer::WindowID p_screen) const {
35113511
return context->surface_get_height(surface);
35123512
}
35133513

3514+
int RenderingDevice::screen_get_pre_rotation_degrees(DisplayServer::WindowID p_screen) const {
3515+
_THREAD_SAFE_METHOD_
3516+
3517+
HashMap<DisplayServer::WindowID, RDD::SwapChainID>::ConstIterator it = screen_swap_chains.find(p_screen);
3518+
ERR_FAIL_COND_V_MSG(it == screen_swap_chains.end(), ERR_CANT_CREATE, "A swap chain was not created for the screen.");
3519+
3520+
return driver->swap_chain_get_pre_rotation_degrees(it->value);
3521+
}
3522+
35143523
RenderingDevice::FramebufferFormatID RenderingDevice::screen_get_framebuffer_format(DisplayServer::WindowID p_screen) const {
35153524
_THREAD_SAFE_METHOD_
35163525

servers/rendering/rendering_device.h

+1
Original file line numberDiff line numberDiff line change
@@ -1057,6 +1057,7 @@ class RenderingDevice : public RenderingDeviceCommons {
10571057
Error screen_prepare_for_drawing(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID);
10581058
int screen_get_width(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;
10591059
int screen_get_height(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;
1060+
int screen_get_pre_rotation_degrees(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;
10601061
FramebufferFormatID screen_get_framebuffer_format(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;
10611062
Error screen_free(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID);
10621063

servers/rendering/rendering_device_driver.h

+3
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,9 @@ class RenderingDeviceDriver : public RenderingDeviceCommons {
453453
// Retrieve the render pass that can be used to draw on the swap chain's framebuffers.
454454
virtual RenderPassID swap_chain_get_render_pass(SwapChainID p_swap_chain) = 0;
455455

456+
// Retrieve the rotation in degrees to apply as a pre-transform. Usually 0 on PC. May be 0, 90, 180 & 270 on Android.
457+
virtual int swap_chain_get_pre_rotation_degrees(SwapChainID p_swap_chain) { return 0; }
458+
456459
// Retrieve the format used by the swap chain's framebuffers.
457460
virtual DataFormat swap_chain_get_format(SwapChainID p_swap_chain) = 0;
458461

0 commit comments

Comments
 (0)