Bladeren bron

android: Fix presentation layout on foldable and tablet devices.

bunnei 3 jaren geleden
bovenliggende
commit
057117f009

+ 24 - 0
src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt

@@ -7,6 +7,7 @@ import android.app.Activity
 import android.content.Context
 import android.content.DialogInterface
 import android.content.Intent
+import android.content.res.Configuration
 import android.graphics.Rect
 import android.hardware.Sensor
 import android.hardware.SensorEvent
@@ -31,6 +32,7 @@ import org.yuzu.yuzu_emu.features.settings.model.Settings
 import org.yuzu.yuzu_emu.fragments.EmulationFragment
 import org.yuzu.yuzu_emu.model.Game
 import org.yuzu.yuzu_emu.utils.ControllerMappingHelper
+import org.yuzu.yuzu_emu.utils.EmulationMenuSettings
 import org.yuzu.yuzu_emu.utils.ForegroundService
 import org.yuzu.yuzu_emu.utils.InputHandler
 import org.yuzu.yuzu_emu.utils.NfcReader
@@ -128,6 +130,11 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
         super.onResume()
         nfcReader.startScanning()
         startMotionSensorListener()
+
+        NativeLibrary.notifyOrientationChange(
+            EmulationMenuSettings.landscapeScreenLayout,
+            getAdjustedRotation()
+        )
     }
 
     override fun onPause() {
@@ -233,6 +240,23 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
 
     override fun onAccuracyChanged(sensor: Sensor, i: Int) {}
 
+    private fun getAdjustedRotation():Int {
+        val rotation = windowManager.defaultDisplay.rotation;
+        val config: Configuration = resources.configuration
+
+        if ((config.screenLayout and Configuration.SCREENLAYOUT_LONG_YES) != 0 ||
+            (config.screenLayout and Configuration.SCREENLAYOUT_LONG_NO) == 0) {
+            return rotation;
+        }
+        when (rotation) {
+            Surface.ROTATION_0 -> return Surface.ROTATION_90;
+            Surface.ROTATION_90 -> return Surface.ROTATION_0;
+            Surface.ROTATION_180 -> return Surface.ROTATION_270;
+            Surface.ROTATION_270 -> return Surface.ROTATION_180;
+        }
+        return rotation;
+    }
+
     private fun restoreState(savedInstanceState: Bundle) {
         game = savedInstanceState.parcelable(EXTRA_SELECTED_GAME)!!
     }

+ 0 - 6
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt

@@ -118,12 +118,6 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
     override fun onStop() {
         super.onStop()
         presenter.onStop(isFinishing)
-
-        // Update framebuffer layout when closing the settings
-        NativeLibrary.notifyOrientationChange(
-            EmulationMenuSettings.landscapeScreenLayout,
-            windowManager.defaultDisplay.rotation
-        )
     }
 
     override fun showSettingsFragment(menuTag: String, addToStack: Boolean, gameId: String) {

+ 5 - 5
src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt

@@ -767,10 +767,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
             var cutoutBottom = 0
             val insets = context.windowManager.currentWindowMetrics.windowInsets.displayCutout
             if (insets != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
-                maxY =
-                    if (insets.boundingRectTop.bottom != 0) insets.boundingRectTop.bottom.toFloat() else maxY
-                maxX =
-                    if (insets.boundingRectRight.left != 0) insets.boundingRectRight.left.toFloat() else maxX
+                if (insets.boundingRectTop.bottom != 0 && insets.boundingRectTop.bottom > maxY / 2)
+                    insets.boundingRectTop.bottom.toFloat() else maxY
+                if (insets.boundingRectRight.left != 0 && insets.boundingRectRight.left > maxX / 2)
+                    insets.boundingRectRight.left.toFloat() else maxX
+
                 minX = insets.boundingRectLeft.right - insets.boundingRectLeft.left
                 minY = insets.boundingRectBottom.top - insets.boundingRectBottom.bottom
 
@@ -778,7 +779,6 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
                 cutoutBottom = insets.boundingRectTop.top - insets.boundingRectTop.bottom
             }
 
-
             // This makes sure that if we have an inset on one side of the screen, we mirror it on
             // the other side. Since removing space from one of the max values messes with the scale,
             // we also have to account for it using our min values.

+ 18 - 3
src/android/app/src/main/jni/native.cpp

@@ -89,8 +89,16 @@ public:
         return m_native_window;
     }
 
-    void SetNativeWindow(ANativeWindow* m_native_window_) {
-        m_native_window = m_native_window_;
+    void SetNativeWindow(ANativeWindow* native_window) {
+        m_native_window = native_window;
+    }
+
+    u32 ScreenRotation() const {
+        return m_screen_rotation;
+    }
+
+    void SetScreenRotation(u32 screen_rotation) {
+        m_screen_rotation = screen_rotation;
     }
 
     void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir,
@@ -379,6 +387,7 @@ private:
     // Window management
     std::unique_ptr<EmuWindow_Android> m_window;
     ANativeWindow* m_native_window{};
+    u32 m_screen_rotation{};
 
     // Core emulation
     Core::System m_system;
@@ -404,6 +413,10 @@ private:
 
 } // Anonymous namespace
 
+u32 GetAndroidScreenRotation() {
+    return EmulationSession::GetInstance().ScreenRotation();
+}
+
 static Core::SystemResultStatus RunEmulation(const std::string& filepath) {
     Common::Log::Initialize();
     Common::Log::SetColorConsoleBackendEnabled(true);
@@ -450,7 +463,9 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_surfaceDestroyed(JNIEnv* env,
 void Java_org_yuzu_yuzu_1emu_NativeLibrary_notifyOrientationChange(JNIEnv* env,
                                                                    [[maybe_unused]] jclass clazz,
                                                                    jint layout_option,
-                                                                   jint rotation) {}
+                                                                   jint rotation) {
+    return EmulationSession::GetInstance().SetScreenRotation(static_cast<u32>(rotation));
+}
 
 void Java_org_yuzu_yuzu_1emu_NativeLibrary_setAppDirectory(JNIEnv* env,
                                                            [[maybe_unused]] jclass clazz,

+ 47 - 8
src/video_core/renderer_vulkan/vk_blit_screen.cpp

@@ -37,6 +37,10 @@
 #include "video_core/vulkan_common/vulkan_memory_allocator.h"
 #include "video_core/vulkan_common/vulkan_wrapper.h"
 
+#ifdef ANDROID
+extern u32 GetAndroidScreenRotation();
+#endif
+
 namespace Vulkan {
 
 namespace {
@@ -74,23 +78,58 @@ struct ScreenRectVertex {
     }
 };
 
-constexpr std::array<f32, 4 * 4> MakeOrthographicMatrix(f32 width, f32 height) {
-    // clang-format off
 #ifdef ANDROID
-    // Android renders in portrait, so rotate the matrix.
-    return { 0.f,          2.f / width, 0.f, 0.f,
-            -2.f / height, 0.f,         0.f, 0.f,
-             0.f,          0.f,         1.f, 0.f,
-             1.f,         -1.f,         0.f, 1.f};
+
+std::array<f32, 4 * 4> MakeOrthographicMatrix(f32 width, f32 height) {
+    constexpr u32 ROTATION_0 = 0;
+    constexpr u32 ROTATION_90 = 1;
+    constexpr u32 ROTATION_180 = 2;
+    constexpr u32 ROTATION_270 = 3;
+
+    // clang-format off
+    switch (GetAndroidScreenRotation()) {
+        case ROTATION_0:
+            // Desktop
+            return { 2.f / width, 0.f,          0.f, 0.f,
+                     0.f,         2.f / height, 0.f, 0.f,
+                     0.f,         0.f,          1.f, 0.f,
+                    -1.f,        -1.f,          0.f, 1.f};
+        case ROTATION_180:
+            // Reverse desktop
+            return {-2.f / width, 0.f,          0.f, 0.f,
+                     0.f,        -2.f / height, 0.f, 0.f,
+                     0.f,         0.f,          1.f, 0.f,
+                     1.f,         1.f,          0.f, 1.f};
+        case ROTATION_270:
+            // Reverse landscape
+            return { 0.f,         -2.f / width, 0.f, 0.f,
+                     2.f / height, 0.f,         0.f, 0.f,
+                     0.f,          0.f,         1.f, 0.f,
+                    -1.f,          1.f,         0.f, 1.f};
+        case ROTATION_90:
+        default:
+            // Landscape
+            return { 0.f,          2.f / width, 0.f, 0.f,
+                    -2.f / height, 0.f,         0.f, 0.f,
+                     0.f,          0.f,         1.f, 0.f,
+                     1.f,         -1.f,         0.f, 1.f};
+    }
+    // clang-format on
+}
+
 #else
+
+std::array<f32, 4 * 4> MakeOrthographicMatrix(f32 width, f32 height) {
+    // clang-format off
     return { 2.f / width, 0.f,          0.f, 0.f,
              0.f,         2.f / height, 0.f, 0.f,
              0.f,         0.f,          1.f, 0.f,
             -1.f,        -1.f,          0.f, 1.f};
-#endif // ANDROID
     // clang-format on
 }
 
+#endif
+
 u32 GetBytesPerPixel(const Tegra::FramebufferConfig& framebuffer) {
     using namespace VideoCore::Surface;
     return BytesPerBlock(PixelFormatFromGPUPixelFormat(framebuffer.pixel_format));