Android: Call Surface.setFrameRate & update it

This commit is contained in:
Luke Street
2026-06-15 23:39:36 -06:00
parent 44cb2c84ba
commit 16cc37ca10
6 changed files with 179 additions and 4 deletions
+74
View File
@@ -0,0 +1,74 @@
#include "dusk/android_frame_rate.hpp"
#if defined(TARGET_ANDROID) || defined(__ANDROID__) || defined(ANDROID)
#include "dusk/settings.h"
#include <SDL3/SDL_system.h>
#include <jni.h>
namespace dusk::android {
namespace {
float preferred_surface_frame_rate() {
switch (getSettings().game.enableFrameInterpolation.getValue()) {
case FrameInterpMode::Off:
return 30.0f;
case FrameInterpMode::Unlimited:
default:
return 0.0f;
case FrameInterpMode::Capped:
return static_cast<float>(getSettings().video.maxFrameRate.getValue());
}
}
bool clear_pending_exception(JNIEnv* env) {
if (env == nullptr || !env->ExceptionCheck()) {
return false;
}
env->ExceptionClear();
return true;
}
} // namespace
void update_surface_frame_rate() {
auto* env = static_cast<JNIEnv*>(SDL_GetAndroidJNIEnv());
if (env == nullptr) {
return;
}
jobject activity = static_cast<jobject>(SDL_GetAndroidActivity());
if (activity == nullptr || clear_pending_exception(env)) {
if (activity != nullptr) {
env->DeleteLocalRef(activity);
}
return;
}
jclass activityClass = env->GetObjectClass(activity);
if (activityClass == nullptr || clear_pending_exception(env)) {
env->DeleteLocalRef(activity);
return;
}
jmethodID setPreferredFrameRate =
env->GetMethodID(activityClass, "setPreferredSurfaceFrameRate", "(F)V");
env->DeleteLocalRef(activityClass);
if (setPreferredFrameRate == nullptr || clear_pending_exception(env)) {
env->DeleteLocalRef(activity);
return;
}
jvalue args[1]{};
args[0].f = preferred_surface_frame_rate();
env->CallVoidMethodA(activity, setPreferredFrameRate, args);
env->DeleteLocalRef(activity);
clear_pending_exception(env);
}
} // namespace dusk::android
#else
namespace dusk::android {
void update_surface_frame_rate() {}
} // namespace dusk::android
#endif
+7
View File
@@ -0,0 +1,7 @@
#pragma once
namespace dusk::android {
void update_surface_frame_rate();
} // namespace dusk::android
+12 -4
View File
@@ -6,6 +6,7 @@
#include "dusk/app_info.hpp"
#include "dusk/audio/DuskAudioSystem.h"
#include "dusk/audio/DuskDsp.hpp"
#include "dusk/android_frame_rate.hpp"
#include "dusk/config.hpp"
#include "dusk/hotkeys.h"
#include "dusk/data.hpp"
@@ -478,14 +479,19 @@ SelectButton& config_percent_select(Pane& leftPane, Pane& rightPane, ConfigVar<f
SelectButton& config_int_select(Pane& leftPane, Pane& rightPane, ConfigVar<int>& var,
Rml::String key, Rml::String helpText, int min, int max, int step = 5,
std::function<bool()> isDisabled = {}, std::string suffix = "") {
std::function<bool()> isDisabled = {}, std::function<void(int)> onChange = {},
std::string suffix = "") {
auto& button = leftPane.add_child<NumberButton>(NumberButton::Props{
.key = std::move(key),
.getValue = [&var] { return var; },
.setValue =
[&var, min, max](int value) {
var.setValue(std::clamp(value, min, max));
[&var, min, max, callback = std::move(onChange)](int value) {
const int clampedValue = std::clamp(value, min, max);
var.setValue(clampedValue);
config::Save();
if (callback) {
callback(clampedValue);
}
},
.isDisabled = std::move(isDisabled),
.isModified = [&var] { return var.getValue() != var.getDefaultValue(); },
@@ -929,6 +935,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
.on_pressed([i] {
mDoAud_seStartMenu(kSoundItemChange);
getSettings().game.enableFrameInterpolation.setValue(static_cast<FrameInterpMode>(i));
android::update_surface_frame_rate();
config::Save();
});
}
@@ -936,7 +943,8 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
});
config_int_select(leftPane, rightPane, getSettings().video.maxFrameRate,
"Framerate Cap", "Limit the framerate to the specified value.", 30, 540, 1,
[] { return getSettings().game.enableFrameInterpolation.getValue() != FrameInterpMode::Capped; });
[] { return getSettings().game.enableFrameInterpolation.getValue() != FrameInterpMode::Capped; },
[](int) { android::update_surface_frame_rate(); });
config_bool_select(leftPane, rightPane, getSettings().game.enableMapBackground,
{
.key = "Enable Mini-Map Shadows",
+2
View File
@@ -47,6 +47,7 @@
#include <system_error>
#include <thread>
#include "SSystem/SComponent/c_API.h"
#include "dusk/android_frame_rate.hpp"
#include "dusk/app_info.hpp"
#include "dusk/crash_handler.h"
#include "dusk/crash_reporting.h"
@@ -555,6 +556,7 @@ int game_main(int argc, char* argv[]) {
dusk::resetForSpeedrunMode();
}
ApplyCVarOverrides(parsed_arg_options["cvar"]);
dusk::android::update_surface_frame_rate();
dusk::crash_reporting::initialize();
dusk::crash_handler::install();
// TODO: How to handle this?