mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-10 05:28:56 +02:00
[android] Quantization for frames + hints Surface
This commit is contained in:
parent
daf972b517
commit
ebb3cda782
2 changed files with 117 additions and 1 deletions
|
|
@ -7,6 +7,7 @@
|
|||
#include <android/native_window_jni.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <dlfcn.h>
|
||||
|
|
@ -29,6 +30,10 @@ void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
|||
m_window_height = 0;
|
||||
window_info.render_surface = nullptr;
|
||||
m_last_frame_rate_hint = -1.0f;
|
||||
m_pending_frame_rate_hint = -1.0f;
|
||||
m_pending_frame_rate_hint_votes = 0;
|
||||
m_smoothed_present_rate = 0.0f;
|
||||
m_last_frame_display_time = {};
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -59,6 +64,7 @@ void EmuWindow_Android::OnTouchReleased(int id) {
|
|||
}
|
||||
|
||||
void EmuWindow_Android::OnFrameDisplayed() {
|
||||
UpdateObservedFrameRate();
|
||||
UpdateFrameRateHint();
|
||||
|
||||
if (!m_first_frame) {
|
||||
|
|
@ -68,6 +74,44 @@ void EmuWindow_Android::OnFrameDisplayed() {
|
|||
}
|
||||
}
|
||||
|
||||
void EmuWindow_Android::UpdateObservedFrameRate() {
|
||||
const auto now = Clock::now();
|
||||
if (m_last_frame_display_time.time_since_epoch().count() != 0) {
|
||||
const auto frame_time = std::chrono::duration<float>(now - m_last_frame_display_time);
|
||||
const float seconds = frame_time.count();
|
||||
if (seconds > 0.0f) {
|
||||
const float instantaneous_rate = 1.0f / seconds;
|
||||
if (std::isfinite(instantaneous_rate) && instantaneous_rate >= 10.0f &&
|
||||
instantaneous_rate <= 240.0f) {
|
||||
constexpr float SmoothingFactor = 0.15f;
|
||||
if (m_smoothed_present_rate <= 0.0f) {
|
||||
m_smoothed_present_rate = instantaneous_rate;
|
||||
} else {
|
||||
m_smoothed_present_rate +=
|
||||
(instantaneous_rate - m_smoothed_present_rate) * SmoothingFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_last_frame_display_time = now;
|
||||
}
|
||||
|
||||
float EmuWindow_Android::QuantizeFrameRateHint(float frame_rate) {
|
||||
if (!std::isfinite(frame_rate) || frame_rate < 20.0f) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
constexpr std::array CandidateRates{30.0f, 45.0f, 60.0f, 90.0f, 120.0f};
|
||||
const auto best = std::min_element(CandidateRates.begin(), CandidateRates.end(),
|
||||
[frame_rate](float lhs, float rhs) {
|
||||
return std::fabs(frame_rate - lhs) <
|
||||
std::fabs(frame_rate - rhs);
|
||||
});
|
||||
const float best_rate = *best;
|
||||
const float tolerance = std::max(best_rate * 0.18f, 5.0f);
|
||||
return std::fabs(frame_rate - best_rate) <= tolerance ? best_rate : 0.0f;
|
||||
}
|
||||
|
||||
float EmuWindow_Android::GetFrameRateHint() const {
|
||||
if (!Settings::values.use_speed_limit.GetValue()) {
|
||||
return 0.0f;
|
||||
|
|
@ -89,7 +133,45 @@ float EmuWindow_Android::GetFrameRateHint() const {
|
|||
return 0.0f;
|
||||
}
|
||||
|
||||
return desired_rate;
|
||||
if (m_last_frame_rate_hint > 0.0f && m_smoothed_present_rate > 0.0f) {
|
||||
const float observed_rate = m_smoothed_present_rate;
|
||||
switch (static_cast<int>(m_last_frame_rate_hint)) {
|
||||
case 30:
|
||||
if (observed_rate < 42.0f) {
|
||||
return 30.0f;
|
||||
}
|
||||
break;
|
||||
case 45:
|
||||
if (observed_rate >= 35.0f && observed_rate < 54.0f) {
|
||||
return 45.0f;
|
||||
}
|
||||
break;
|
||||
case 60:
|
||||
if (observed_rate >= 48.0f && observed_rate < 75.0f) {
|
||||
return 60.0f;
|
||||
}
|
||||
break;
|
||||
case 90:
|
||||
if (observed_rate >= 74.0f && observed_rate < 105.0f) {
|
||||
return 90.0f;
|
||||
}
|
||||
break;
|
||||
case 120:
|
||||
if (observed_rate >= 100.0f) {
|
||||
return 120.0f;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const float observed_hint = QuantizeFrameRateHint(m_smoothed_present_rate);
|
||||
if (observed_hint > 0.0f) {
|
||||
return observed_hint;
|
||||
}
|
||||
|
||||
return QuantizeFrameRateHint(desired_rate);
|
||||
}
|
||||
|
||||
void EmuWindow_Android::UpdateFrameRateHint() {
|
||||
|
|
@ -100,9 +182,28 @@ void EmuWindow_Android::UpdateFrameRateHint() {
|
|||
|
||||
const float frame_rate_hint = GetFrameRateHint();
|
||||
if (std::fabs(frame_rate_hint - m_last_frame_rate_hint) < 0.01f) {
|
||||
m_pending_frame_rate_hint = frame_rate_hint;
|
||||
m_pending_frame_rate_hint_votes = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (frame_rate_hint == 0.0f) {
|
||||
m_pending_frame_rate_hint = frame_rate_hint;
|
||||
m_pending_frame_rate_hint_votes = 0;
|
||||
} else if (m_last_frame_rate_hint >= 0.0f) {
|
||||
if (std::fabs(frame_rate_hint - m_pending_frame_rate_hint) >= 0.01f) {
|
||||
m_pending_frame_rate_hint = frame_rate_hint;
|
||||
m_pending_frame_rate_hint_votes = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
++m_pending_frame_rate_hint_votes;
|
||||
constexpr std::uint32_t StableVoteThreshold = 12;
|
||||
if (m_pending_frame_rate_hint_votes < StableVoteThreshold) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
using SetFrameRateWithChangeStrategyFn =
|
||||
int32_t (*)(ANativeWindow*, float, int8_t, int8_t);
|
||||
static const auto set_frame_rate_with_change_strategy =
|
||||
|
|
@ -123,6 +224,8 @@ void EmuWindow_Android::UpdateFrameRateHint() {
|
|||
}
|
||||
|
||||
m_last_frame_rate_hint = frame_rate_hint;
|
||||
m_pending_frame_rate_hint = frame_rate_hint;
|
||||
m_pending_frame_rate_hint_votes = 0;
|
||||
}
|
||||
|
||||
EmuWindow_Android::EmuWindow_Android(ANativeWindow* surface,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,13 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
|
||||
|
|
@ -50,8 +55,12 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
using Clock = std::chrono::steady_clock;
|
||||
|
||||
void UpdateFrameRateHint();
|
||||
void UpdateObservedFrameRate();
|
||||
[[nodiscard]] float GetFrameRateHint() const;
|
||||
[[nodiscard]] static float QuantizeFrameRateHint(float frame_rate);
|
||||
|
||||
float m_window_width{};
|
||||
float m_window_height{};
|
||||
|
|
@ -60,4 +69,8 @@ private:
|
|||
|
||||
bool m_first_frame = false;
|
||||
float m_last_frame_rate_hint = -1.0f;
|
||||
float m_pending_frame_rate_hint = -1.0f;
|
||||
float m_smoothed_present_rate = 0.0f;
|
||||
Clock::time_point m_last_frame_display_time{};
|
||||
std::uint32_t m_pending_frame_rate_hint_votes = 0;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue