Android: Add 'Sync To Host Refresh Rate' option

This commit is contained in:
Connor McLaughlin 2021-01-11 15:41:20 +10:00
parent 873b9f622a
commit c18fa06f0c
6 changed files with 47 additions and 3 deletions

View File

@ -18,9 +18,9 @@ A "BIOS" ROM image is required to to start the emulator and to play games. You c
## Latest News
Older entries are available at https://github.com/stenzek/duckstation/blob/master/NEWS.md
- 2020/01/10: Option to sync to host refresh rate added (enabled by default). This will give the smoothest animation possible with zero duped frames, at the cost of running the game <1% faster. Users with variable refresh rate (GSync/FreeSync) displays will want to disable the option.
- 2020/01/10: Audio resampling added when fast forwarding to fixed speeds. Instead of crackling audio, you'll now get pitch altered audio.
- 2020/01/03: Per game settings and game properties added to Android version.
- 2021/01/10: Option to sync to host refresh rate added (enabled by default). This will give the smoothest animation possible with zero duped frames, at the cost of running the game <1% faster. Users with variable refresh rate (GSync/FreeSync) displays will want to disable the option.
- 2021/01/10: Audio resampling added when fast forwarding to fixed speeds. Instead of crackling audio, you'll now get pitch altered audio.
- 2021/01/03: Per game settings and game properties added to Android version.
- 2020/12/30: Box and Adaptive downsampling modes added. Adaptive downsampling will smooth 2D backgrounds but attempt to preserve 3D geometry via pixel similarity (only supported in D3D11/Vulkan). Box is a simple average filter which will downsample to native resolution.
- 2020/12/30: Hotkey binding added to Android version. You can now bind hotkeys such as fast forward, save state, etc to controller buttons. The ability to bind multi-button combinations will be added in the future.
- 2020/12/29: Controller mapping/binding added for Android version. By default mappings will be clear and you will have to set them, you can do this from `Settings -> Controllers -> Controller Mapping`. Profiles can be saved and loaded as well.

View File

@ -44,6 +44,7 @@ static jmethodID s_EmulationActivity_method_onEmulationStarted;
static jmethodID s_EmulationActivity_method_onEmulationStopped;
static jmethodID s_EmulationActivity_method_onGameTitleChanged;
static jmethodID s_EmulationActivity_method_setVibration;
static jmethodID s_EmulationActivity_method_getRefreshRate;
static jclass s_PatchCode_class;
static jmethodID s_PatchCode_constructor;
static jclass s_GameListEntry_class;
@ -223,6 +224,20 @@ std::unique_ptr<ByteStream> AndroidHostInterface::OpenPackageFile(const char* pa
return ret;
}
bool AndroidHostInterface::GetMainDisplayRefreshRate(float* refresh_rate)
{
if (!m_emulation_activity_object)
return false;
float value = AndroidHelpers::GetJNIEnv()->CallFloatMethod(m_emulation_activity_object,
s_EmulationActivity_method_getRefreshRate);
if (value <= 0.0f)
return false;
*refresh_rate = value;
return true;
}
void AndroidHostInterface::SetUserDirectory()
{
// Already set in constructor.
@ -881,6 +896,8 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
env->GetMethodID(s_EmulationActivity_class, "onGameTitleChanged", "(Ljava/lang/String;)V")) == nullptr ||
(s_EmulationActivity_method_setVibration = env->GetMethodID(emulation_activity_class, "setVibration", "(Z)V")) ==
nullptr ||
(s_EmulationActivity_method_getRefreshRate =
env->GetMethodID(emulation_activity_class, "getRefreshRate", "()F")) == nullptr ||
(s_PatchCode_constructor = env->GetMethodID(s_PatchCode_class, "<init>", "(ILjava/lang/String;Z)V")) == nullptr ||
(s_GameListEntry_constructor = env->GetMethodID(
s_GameListEntry_class, "<init>",

View File

@ -38,6 +38,7 @@ public:
int GetIntSettingValue(const char* section, const char* key, int default_value = 0) override;
float GetFloatSettingValue(const char* section, const char* key, float default_value = 0.0f) override;
std::unique_ptr<ByteStream> OpenPackageFile(const char* path, u32 flags) override;
bool GetMainDisplayRefreshRate(float* refresh_rate) override;
bool IsEmulationThreadRunning() const { return m_emulation_thread_running.load(); }
bool IsEmulationThreadPaused() const;

View File

@ -11,10 +11,12 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Vibrator;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.Toast;
@ -137,6 +139,21 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
});
}
public float getRefreshRate() {
WindowManager windowManager = getWindowManager();
if (windowManager == null) {
windowManager = ((WindowManager) getSystemService(Context.WINDOW_SERVICE));
if (windowManager == null)
return -1.0f;
}
Display display = windowManager.getDefaultDisplay();
if (display == null)
return -1.0f;
return display.getRefreshRate();
}
private void doApplySettings() {
AndroidHostInterface.getInstance().applySettings();
updateRequestedOrientation();

View File

@ -191,4 +191,6 @@
<string name="game_properties_tab_controller_settings">Controller Settings</string>
<string name="settings_audio_resampling">Audio Resampling</string>
<string name="settings_summary_audio_resampling">When running outside of 100% speed, resamples audio from the target speed instead of dropping frames. Produces much nicer fast forward/slowdown audio at a small cost to performance.</string>
<string name="settings_general_sync_to_host_refresh_rate">Sync To Host Refresh Rate</string>
<string name="settings_summary_general_sync_to_host_refresh_rate">Adjusts the emulation speed so the console\'s refresh rate matches the host\'s refresh rate, when VSync and Audio Resampling is enabled. This results in the smoothest animations possible, at the cost of potentially increasing the emulation speed by less than 1%.</string>
</resources>

View File

@ -78,6 +78,13 @@
app:defaultValue="false"
app:summary="@string/settings_summary_video_sync"
app:iconSpaceReserved="false" />
<SwitchPreferenceCompat
app:key="Main/SyncToHostRefreshRate"
app:title="@string/settings_general_sync_to_host_refresh_rate"
app:defaultValue="false"
app:summary="@string/settings_summary_general_sync_to_host_refresh_rate"
app:dependency="Display/VSync"
app:iconSpaceReserved="false" />
<ListPreference
app:key="Console/Region"
app:title="@string/settings_console_region"