Implement fixed aspect ratio surface

Adds a setting to letterbox the surface with black bars to 16:9 or 21:9 aspect ratio to avoid stretching out the rendered image
This commit is contained in:
MCredstoner2004 2022-01-12 09:24:29 -06:00 committed by ◱ Mark
parent 6cf9bc5729
commit 0ceecbba4f
7 changed files with 90 additions and 31 deletions

View File

@ -12,6 +12,7 @@ import android.content.res.AssetManager
import android.graphics.PointF import android.graphics.PointF
import android.os.* import android.os.*
import android.util.Log import android.util.Log
import android.util.Rational
import android.view.* import android.view.*
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isGone import androidx.core.view.isGone
@ -221,9 +222,6 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
returnFromEmulation() returnFromEmulation()
} }
/**
* This makes the window fullscreen, sets up the performance statistics and finally calls [executeApplication] for executing the application
*/
@SuppressLint("SetTextI18n", "ClickableViewAccessibility") @SuppressLint("SetTextI18n", "ClickableViewAccessibility")
override fun onCreate(savedInstanceState : Bundle?) { override fun onCreate(savedInstanceState : Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -237,6 +235,14 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
binding.gameView.holder.addCallback(this) binding.gameView.holder.addCallback(this)
binding.gameView.setAspectRatio(
when (settings.aspectRatio) {
0 -> Rational(16, 9)
1 -> Rational(21, 9)
else -> null
}
)
if (settings.perfStats) { if (settings.perfStats) {
binding.perfStats.apply { binding.perfStats.apply {
postDelayed(object : Runnable { postDelayed(object : Runnable {

View File

@ -38,5 +38,7 @@ class Settings @Inject constructor(@ApplicationContext private val context : Con
var maxRefreshRate by sharedPreferences(context, false) var maxRefreshRate by sharedPreferences(context, false)
var aspectRatio by sharedPreferences(context, 0)
var systemLanguage by sharedPreferences(context, 1) var systemLanguage by sharedPreferences(context, 1)
} }

View File

@ -0,0 +1,39 @@
package emu.skyline.views
import android.content.Context
import android.util.AttributeSet
import android.util.Rational
import android.view.SurfaceView
import kotlin.math.roundToInt
class FixedRatioSurfaceView @JvmOverloads constructor(context : Context, attrs : AttributeSet? = null, defStyleAttr : Int = 0) : SurfaceView(context, attrs, defStyleAttr) {
private var aspectRatio : Float = 0f // (width / height), 0f is a special value for stretch
/**
* Sets the desired aspect ratio for this view
* @param ratio the ratio to force the view to, or null to stretch to fit
*/
fun setAspectRatio(ratio : Rational?) {
aspectRatio = ratio?.toFloat() ?: 0f
}
override fun onMeasure(widthMeasureSpec : Int, heightMeasureSpec : Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val width = MeasureSpec.getSize(widthMeasureSpec)
val height = MeasureSpec.getSize(heightMeasureSpec)
if (aspectRatio != 0f) {
val newWidth : Int
val newHeight : Int
if (height * aspectRatio < width) {
newWidth = (height * aspectRatio).roundToInt()
newHeight = height
} else {
newWidth = width
newHeight = (width / aspectRatio).roundToInt()
}
setMeasuredDimension(newWidth, newHeight)
} else {
setMeasuredDimension(width, height)
}
}
}

View File

@ -5,14 +5,14 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:keepScreenOn="true" android:keepScreenOn="true"
tools:background="@android:color/black" android:background="@android:color/black"
tools:context=".EmulationActivity"> tools:context=".EmulationActivity">
<SurfaceView <emu.skyline.views.FixedRatioSurfaceView
android:id="@+id/game_view" android:id="@+id/game_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:visibility="invisible" /> android:layout_gravity="center" />
<emu.skyline.input.onscreen.OnScreenControllerView <emu.skyline.input.onscreen.OnScreenControllerView
android:id="@+id/on_screen_controller_view" android:id="@+id/on_screen_controller_view"

View File

@ -74,4 +74,9 @@
<item>7</item> <item>7</item>
<item>11</item> <item>11</item>
</integer-array> </integer-array>
<string-array name="aspect_ratios">
<item>16:9 (Switch, Recommended)</item>
<item>21:9 (Ultrawide Mods)</item>
<item>Device Aspect Ratio (Stretch to fit)</item>
</string-array>
</resources> </resources>

View File

@ -61,6 +61,7 @@
<string name="max_refresh_rate">Use Maximum Display Refresh Rate</string> <string name="max_refresh_rate">Use Maximum Display Refresh Rate</string>
<string name="max_refresh_rate_enabled">Sets the display refresh rate as high as possible (Will break most games)</string> <string name="max_refresh_rate_enabled">Sets the display refresh rate as high as possible (Will break most games)</string>
<string name="max_refresh_rate_disabled">Sets the display refresh rate to 60Hz</string> <string name="max_refresh_rate_disabled">Sets the display refresh rate to 60Hz</string>
<string name="aspect_ratio">Aspect Ratio</string>
<!-- Input --> <!-- Input -->
<string name="input">Input</string> <string name="input">Input</string>
<string name="osc">On-Screen Controls</string> <string name="osc">On-Screen Controls</string>

View File

@ -103,6 +103,12 @@
android:summaryOn="@string/max_refresh_rate_enabled" android:summaryOn="@string/max_refresh_rate_enabled"
app:key="max_refresh_rate" app:key="max_refresh_rate"
app:title="@string/max_refresh_rate" /> app:title="@string/max_refresh_rate" />
<emu.skyline.preference.IntegerListPreference
android:defaultValue="0"
android:entries="@array/aspect_ratios"
app:key="aspect_ratio"
app:title="@string/aspect_ratio"
app:useSimpleSummaryProvider="true" />
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory <PreferenceCategory
android:key="category_input" android:key="category_input"