mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-26 06:22:45 +00:00
Improve display mode selection algorithm
- Allow the refresh rate to drop if it results in a better match for the stream frame rate - Allow the resolution to drop for > 60 FPS streams to allow matching a higher refresh rate
This commit is contained in:
parent
8f55517236
commit
17c47a15da
@ -616,6 +616,11 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isRefreshRateGoodMatch(float refreshRate) {
|
||||||
|
return refreshRate >= prefConfig.fps &&
|
||||||
|
Math.round(refreshRate) % prefConfig.fps <= 3;
|
||||||
|
}
|
||||||
|
|
||||||
private float prepareDisplayForRendering() {
|
private float prepareDisplayForRendering() {
|
||||||
Display display = getWindowManager().getDefaultDisplay();
|
Display display = getWindowManager().getDefaultDisplay();
|
||||||
WindowManager.LayoutParams windowLayoutParams = getWindow().getAttributes();
|
WindowManager.LayoutParams windowLayoutParams = getWindow().getAttributes();
|
||||||
@ -624,41 +629,59 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
// On M, we can explicitly set the optimal display mode
|
// On M, we can explicitly set the optimal display mode
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
Display.Mode bestMode = display.getMode();
|
Display.Mode bestMode = display.getMode();
|
||||||
|
boolean refreshRateIsGood = isRefreshRateGoodMatch(bestMode.getRefreshRate());
|
||||||
for (Display.Mode candidate : display.getSupportedModes()) {
|
for (Display.Mode candidate : display.getSupportedModes()) {
|
||||||
boolean refreshRateOk = candidate.getRefreshRate() >= bestMode.getRefreshRate();
|
boolean refreshRateReduced = candidate.getRefreshRate() < bestMode.getRefreshRate();
|
||||||
boolean resolutionOk = candidate.getPhysicalWidth() >= bestMode.getPhysicalWidth() &&
|
boolean resolutionReduced = candidate.getPhysicalWidth() < bestMode.getPhysicalWidth() ||
|
||||||
candidate.getPhysicalHeight() >= bestMode.getPhysicalHeight() &&
|
candidate.getPhysicalHeight() < bestMode.getPhysicalHeight();
|
||||||
candidate.getPhysicalWidth() <= 4096;
|
boolean resolutionFitsStream = candidate.getPhysicalWidth() >= prefConfig.width &&
|
||||||
|
candidate.getPhysicalHeight() >= prefConfig.height;
|
||||||
|
|
||||||
LimeLog.info("Examining display mode: "+candidate.getPhysicalWidth()+"x"+
|
LimeLog.info("Examining display mode: "+candidate.getPhysicalWidth()+"x"+
|
||||||
candidate.getPhysicalHeight()+"x"+candidate.getRefreshRate());
|
candidate.getPhysicalHeight()+"x"+candidate.getRefreshRate());
|
||||||
|
|
||||||
// On non-4K streams, we force the resolution to never change
|
if (candidate.getPhysicalWidth() > 4096) {
|
||||||
if (prefConfig.width < 3840) {
|
// Avoid resolutions options above 4K to be safe
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// On non-4K streams, we force the resolution to never change unless it's above
|
||||||
|
// 60 FPS, which may require a resolution reduction due to HDMI bandwidth limitations.
|
||||||
|
if (prefConfig.width < 3840 && prefConfig.fps <= 60) {
|
||||||
if (display.getMode().getPhysicalWidth() != candidate.getPhysicalWidth() ||
|
if (display.getMode().getPhysicalWidth() != candidate.getPhysicalWidth() ||
|
||||||
display.getMode().getPhysicalHeight() != candidate.getPhysicalHeight()) {
|
display.getMode().getPhysicalHeight() != candidate.getPhysicalHeight()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the frame rate stays around 60 Hz for <= 60 FPS streams
|
// Make sure the resolution doesn't regress unless if it's over 60 FPS
|
||||||
if (prefConfig.fps <= 60) {
|
// where we may need to reduce resolution to achieve the desired refresh rate.
|
||||||
if (candidate.getRefreshRate() >= 63) {
|
if (resolutionReduced && !(prefConfig.fps > 60 && resolutionFitsStream)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (refreshRateIsGood) {
|
||||||
|
// We have a good matching refresh rate, so we're looking for equal or greater
|
||||||
|
// that is also a good matching refresh rate for our stream frame rate.
|
||||||
|
if (refreshRateReduced || !isRefreshRateGoodMatch(candidate.getRefreshRate())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (!isRefreshRateGoodMatch(candidate.getRefreshRate())) {
|
||||||
// Make sure the refresh rate doesn't regress
|
// We didn't have a good match and this match isn't good either, so just don't
|
||||||
if (!refreshRateOk) {
|
// reduce the refresh rate.
|
||||||
continue;
|
if (refreshRateReduced) {
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
// Make sure the resolution doesn't regress
|
} else {
|
||||||
if (!resolutionOk) {
|
// We didn't have a good match and this match is good. Prefer this refresh rate
|
||||||
continue;
|
// even if it reduces the refresh rate. Lowering the refresh rate can be beneficial
|
||||||
|
// when streaming a 60 FPS stream on a 90 Hz device. We want to select 60 Hz to
|
||||||
|
// match the frame rate even if the active display mode is 90 Hz.
|
||||||
}
|
}
|
||||||
|
|
||||||
bestMode = candidate;
|
bestMode = candidate;
|
||||||
|
refreshRateIsGood = isRefreshRateGoodMatch(candidate.getRefreshRate());
|
||||||
}
|
}
|
||||||
LimeLog.info("Selected display mode: "+bestMode.getPhysicalWidth()+"x"+
|
LimeLog.info("Selected display mode: "+bestMode.getPhysicalWidth()+"x"+
|
||||||
bestMode.getPhysicalHeight()+"x"+bestMode.getRefreshRate());
|
bestMode.getPhysicalHeight()+"x"+bestMode.getRefreshRate());
|
||||||
@ -669,9 +692,9 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
float bestRefreshRate = display.getRefreshRate();
|
float bestRefreshRate = display.getRefreshRate();
|
||||||
for (float candidate : display.getSupportedRefreshRates()) {
|
for (float candidate : display.getSupportedRefreshRates()) {
|
||||||
if (candidate > bestRefreshRate) {
|
LimeLog.info("Examining refresh rate: "+candidate);
|
||||||
LimeLog.info("Examining refresh rate: "+candidate);
|
|
||||||
|
|
||||||
|
if (candidate > bestRefreshRate) {
|
||||||
// Ensure the frame rate stays around 60 Hz for <= 60 FPS streams
|
// Ensure the frame rate stays around 60 Hz for <= 60 FPS streams
|
||||||
if (prefConfig.fps <= 60) {
|
if (prefConfig.fps <= 60) {
|
||||||
if (candidate >= 63) {
|
if (candidate >= 63) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user