Set frame rate GTE to Max for MRR
For animation, scroll/fling, and other velocity, the frame rate might
change after start, which can be specified with GTE setFrameRate.
However changing display refresh rate on an MRR
device will jank, so the stand-in solution is to equate GTE votes to Max
for MRR.
Bug: 330222554
Test: atest libsurfaceflinger_unittest
Test: ABTD
Change-Id: I95dda0048ed6ac749c226221f708bd1303924fdb
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 974c837..a819b79 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -280,9 +280,18 @@
case Layer::FrameRateCompatibility::Exact:
return LayerVoteType::ExplicitExact;
case Layer::FrameRateCompatibility::Gte:
- return LayerVoteType::ExplicitGte;
+ if (isVrrDevice) {
+ return LayerVoteType::ExplicitGte;
+ } else {
+ // For MRR, treat GTE votes as Max because it is used for animations and
+ // scroll. MRR cannot change frame rate without jank, so it should
+ // prefer smoothness.
+ return LayerVoteType::Max;
+ }
}
}();
+ const bool isValuelessVote = voteType == LayerVoteType::NoVote ||
+ voteType == LayerVoteType::Min || voteType == LayerVoteType::Max;
if (FlagManager::getInstance().game_default_frame_rate()) {
// Determine the layer frame rate considering the following priorities:
@@ -307,7 +316,8 @@
gameModeFrameRateOverride.getIntValue());
}
} else if (frameRate.isValid() && frameRate.isVoteValidForMrr(isVrrDevice)) {
- info->setLayerVote({setFrameRateVoteType, frameRate.vote.rate,
+ info->setLayerVote({setFrameRateVoteType,
+ isValuelessVote ? 0_Hz : frameRate.vote.rate,
frameRate.vote.seamlessness, frameRate.category});
if (CC_UNLIKELY(mTraceEnabled)) {
trace(*info, gameFrameRateOverrideVoteType,
@@ -335,8 +345,8 @@
} else {
if (frameRate.isValid() && frameRate.isVoteValidForMrr(isVrrDevice)) {
const auto type = info->isVisible() ? voteType : LayerVoteType::NoVote;
- info->setLayerVote({type, frameRate.vote.rate, frameRate.vote.seamlessness,
- frameRate.category});
+ info->setLayerVote({type, isValuelessVote ? 0_Hz : frameRate.vote.rate,
+ frameRate.vote.seamlessness, frameRate.category});
} else {
if (!frameRate.isVoteValidForMrr(isVrrDevice)) {
ATRACE_FORMAT_INSTANT("Reset layer to ignore explicit vote on MRR %s: %s "
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp
index 5f17128..21b72472 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp
@@ -563,8 +563,25 @@
return vote.type == FrameRateCompatibility::NoVote;
}
+bool LayerInfo::FrameRate::isValuelessType() const {
+ // For a valueless frame rate compatibility (type), the frame rate should be unspecified (0 Hz).
+ if (!isApproxEqual(vote.rate, 0_Hz)) {
+ return false;
+ }
+ switch (vote.type) {
+ case FrameRateCompatibility::Min:
+ case FrameRateCompatibility::NoVote:
+ return true;
+ case FrameRateCompatibility::Default:
+ case FrameRateCompatibility::ExactOrMultiple:
+ case FrameRateCompatibility::Exact:
+ case FrameRateCompatibility::Gte:
+ return false;
+ }
+}
+
bool LayerInfo::FrameRate::isValid() const {
- return isNoVote() || vote.rate.isValid() || category != FrameRateCategory::Default;
+ return isValuelessType() || vote.rate.isValid() || category != FrameRateCategory::Default;
}
bool LayerInfo::FrameRate::isVoteValidForMrr(bool isVrrDevice) const {
@@ -572,7 +589,7 @@
return true;
}
- if (category == FrameRateCategory::Default && vote.type != FrameRateCompatibility::Gte) {
+ if (category == FrameRateCategory::Default) {
return true;
}
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h
index 40903ed..a7847bc 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.h
+++ b/services/surfaceflinger/Scheduler/LayerInfo.h
@@ -146,6 +146,9 @@
// selection.
bool isNoVote() const;
+ // Returns true if the FrameRate has a valid valueless (0 Hz) frame rate type.
+ bool isValuelessType() const;
+
// Checks whether the given FrameRate's vote specifications is valid for MRR devices
// given the current flagging.
bool isVoteValidForMrr(bool isVrrDevice) const;