Skip to content

Commit

Permalink
Merge pull request #18529 from hrydgard/android-60hz
Browse files Browse the repository at this point in the history
Android: Add option to ask system for 60hz output
  • Loading branch information
hrydgard committed Dec 12, 2023
2 parents 144ecf0 + a6d717c commit 7762ccd
Show file tree
Hide file tree
Showing 14 changed files with 94 additions and 11 deletions.
3 changes: 2 additions & 1 deletion Core/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ static int FastForwardModeFromString(const std::string &s) {
return DefaultFastForwardMode();
}

std::string FastForwardModeToString(int v) {
static std::string FastForwardModeToString(int v) {
switch (FastForwardMode(v)) {
case FastForwardMode::CONTINUOUS:
return "CONTINUOUS";
Expand All @@ -592,6 +592,7 @@ static const ConfigSetting graphicsSettings[] = {
ConfigSetting("D3D11Device", &g_Config.sD3D11Device, "", CfgFlag::DEFAULT),
#endif
ConfigSetting("CameraDevice", &g_Config.sCameraDevice, "", CfgFlag::DEFAULT),
ConfigSetting("DisplayFramerateMode", &g_Config.iDisplayFramerateMode, 0, CfgFlag::DEFAULT),
ConfigSetting("VendorBugChecksEnabled", &g_Config.bVendorBugChecksEnabled, true, CfgFlag::DONT_SAVE),
ConfigSetting("UseGeometryShader", &g_Config.bUseGeometryShader, false, CfgFlag::PER_GAME),
ConfigSetting("SkipBufferEffects", &g_Config.bSkipBufferEffects, false, CfgFlag::PER_GAME | CfgFlag::REPORT),
Expand Down
1 change: 1 addition & 0 deletions Core/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ struct Config {
std::string sD3D11Device; // Windows only
std::string sCameraDevice;
std::string sMicDevice;
int iDisplayFramerateMode; // enum DisplayFramerateMode. Android-only.

bool bSoftwareRendering;
bool bSoftwareRenderingJit;
Expand Down
8 changes: 8 additions & 0 deletions Core/ConfigValues.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,11 @@ enum class DebugOverlay : int {
GPU_ALLOCATOR,
FRAMEBUFFER_LIST,
};

// Android-only for now
enum class DisplayFramerateMode : int {
DEFAULT,
REQUEST_60HZ,
FORCE_60HZ_METHOD1,
FORCE_60HZ_METHOD2,
};
4 changes: 4 additions & 0 deletions Core/HLE/sceDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,10 @@ void __DisplayFlip(int cyclesLate) {
postEffectRequiresFlip = duplicateFrames || g_Config.bShaderChainRequires60FPS;
}

if (!FrameTimingThrottled()) {
NOTICE_LOG(SYSTEM, "Throttle: %d %d", (int)fastForwardSkipFlip, (int)postEffectRequiresFlip);
}

const bool fbDirty = gpu->FramebufferDirty();

bool needFlip = fbDirty || noRecentFlip || postEffectRequiresFlip;
Expand Down
18 changes: 11 additions & 7 deletions UI/ControlMappingScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,10 @@ void TouchTestScreen::axis(const AxisInput &axis) {
void TouchTestScreen::DrawForeground(UIContext &dc) {
Bounds bounds = dc.GetLayoutBounds();

double now = time_now_d();
double delta = now - lastFrameTime_;
lastFrameTime_ = now;

dc.BeginNoTex();
for (int i = 0; i < MAX_TOUCH_POINTS; i++) {
if (touches_[i].id != -1) {
Expand Down Expand Up @@ -747,19 +751,19 @@ void TouchTestScreen::DrawForeground(UIContext &dc) {
#endif
"dp_res: %dx%d pixel_res: %dx%d\n"
"g_dpi: %0.3f g_dpi_scale: %0.3fx%0.3f\n"
"g_dpi_scale_real: %0.3fx%0.3f\n%s",
"g_dpi_scale_real: %0.3fx%0.3f\n"
"delta: %0.2f ms fps: %0.3f\n%s",
#if PPSSPP_PLATFORM(ANDROID)
System_GetPropertyInt(SYSPROP_DISPLAY_XRES), System_GetPropertyInt(SYSPROP_DISPLAY_YRES),
#endif
g_display.dp_xres, g_display.dp_yres,
g_display.pixel_xres, g_display.pixel_yres,
g_display.dpi,
g_display.dpi_scale_x, g_display.dpi_scale_y,
g_display.dpi_scale_real_x, g_display.dpi_scale_real_y, extra_debug);
g_display.dp_xres, g_display.dp_yres, g_display.pixel_xres, g_display.pixel_yres,
g_display.dpi, g_display.dpi_scale_x, g_display.dpi_scale_y,
g_display.dpi_scale_real_x, g_display.dpi_scale_real_y,
delta * 1000.0, 1.0 / delta,
extra_debug);

// On Android, also add joystick debug data.


dc.DrawTextShadow(buffer, bounds.centerX(), bounds.y + 20.0f, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII);
dc.Flush();
}
Expand Down
2 changes: 2 additions & 0 deletions UI/ControlMappingScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ class TouchTestScreen : public UIDialogScreenWithGameBackground {

UI::TextView *lastKeyEvents_ = nullptr;

double lastFrameTime_ = 0.0;

void CreateViews() override;
void UpdateLogView();

Expand Down
13 changes: 13 additions & 0 deletions UI/GameSettingsScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1731,6 +1731,19 @@ void DeveloperToolsScreen::CreateViews() {
list->Add(new CheckBox(&g_Config.bGpuLogProfiler, dev->T("GPU log profiler")));
}

#if PPSSPP_PLATFORM(ANDROID)
static const char *framerateModes[] = { "Default", "Request 60Hz", "Force 60Hz 1", "Force 60Hz 2" };
PopupMultiChoice *framerateMode = list->Add(new PopupMultiChoice(&g_Config.iDisplayFramerateMode, gr->T("Framerate mode"), framerateModes, 0, ARRAY_SIZE(framerateModes), I18NCat::GRAPHICS, screenManager()));
framerateMode->SetEnabledFunc([]() { return System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= 30; });
if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) < 31) {
framerateMode->HideChoice(3); // not available
}
framerateMode->OnChoice.Add([this](UI::EventParams &e) {
System_Notify(SystemNotification::FORCE_RECREATE_ACTIVITY);
return UI::EVENT_DONE;
});
#endif

static const char *ffModes[] = { "Render all frames", "", "Frame Skipping" };
PopupMultiChoice *ffMode = list->Add(new PopupMultiChoice(&g_Config.iFastForwardMode, dev->T("Fast-forward mode"), ffModes, 0, ARRAY_SIZE(ffModes), I18NCat::GRAPHICS, screenManager()));
ffMode->SetEnabledFunc([]() { return !g_Config.bVSync; });
Expand Down
4 changes: 4 additions & 0 deletions android/jni/app-android.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1464,6 +1464,10 @@ extern "C" jint JNICALL Java_org_ppsspp_ppsspp_NativeApp_getDesiredBackbufferHei
return desiredBackbufferSizeY;
}

extern "C" jint JNICALL Java_org_ppsspp_ppsspp_NativeApp_getDisplayFramerateMode(JNIEnv *, jclass) {
return g_Config.iDisplayFramerateMode;
}

std::vector<std::string> System_GetCameraDeviceList() {
jclass cameraClass = findClass("org/ppsspp/ppsspp/CameraHelper");
jmethodID deviceListMethod = getEnv()->GetStaticMethodID(cameraClass, "getDeviceList", "()Ljava/util/ArrayList;");
Expand Down
36 changes: 36 additions & 0 deletions android/src/org/ppsspp/ppsspp/NativeActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,7 @@ public void onCreate(Bundle savedInstanceState) {
// mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 8);
// }
}

mGLSurfaceView.setRenderer(nativeRenderer);
setContentView(mGLSurfaceView);
} else {
Expand All @@ -661,6 +662,37 @@ public void onWindowFocusChanged(boolean hasFocus) {
}
}

private void applyFrameRate(Surface surface, float frameRateHz) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
return;
if (mSurface != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
try {
int method = NativeApp.getDisplayFramerateMode();
if (method > 0) {
Log.i(TAG, "Setting desired framerate to " + frameRateHz + " Hz method=" + method);
switch (method) {
case 1:
mSurface.setFrameRate(frameRateHz, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT);
break;
case 2:
mSurface.setFrameRate(frameRateHz, Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE);
break;
case 3:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
mSurface.setFrameRate(frameRateHz, Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, Surface.CHANGE_FRAME_RATE_ALWAYS);
}
break;
default:
break;
}

}
} catch (Exception e) {
Log.e(TAG, "Failed to set framerate: " + e.toString());
}
}
}

public void notifySurface(Surface surface) {
mSurface = surface;

Expand All @@ -676,6 +708,8 @@ public void notifySurface(Surface surface) {
} else {
startRenderLoopThread();
}
} else if (mSurface != null) {
applyFrameRate(mSurface, 60.0f);
}
updateSustainedPerformanceMode();
}
Expand All @@ -692,6 +726,8 @@ protected synchronized void startRenderLoopThread() {
}

Log.w(TAG, "startRenderLoopThread: Starting thread");

applyFrameRate(mSurface, 60.0f);
runVulkanRenderLoop(mSurface);
}

Expand Down
1 change: 1 addition & 0 deletions android/src/org/ppsspp/ppsspp/NativeApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public class NativeApp {
public static native String queryConfig(String queryName);

public static native int getSelectedCamera();
public static native int getDisplayFramerateMode();
public static native void setGpsDataAndroid(long time, float hdop, float latitude, float longitude, float altitude, float speed, float bearing);
public static native void setSatInfoAndroid(short index, short id, short elevation, short azimuth, short snr, short good);
public static native void pushCameraImageAndroid(byte[] image);
Expand Down
3 changes: 3 additions & 0 deletions android/src/org/ppsspp/ppsspp/NativeGLView.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import android.os.Handler;
import android.util.Log;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceControl;

import com.bda.controller.Controller;
import com.bda.controller.ControllerListener;
Expand All @@ -43,6 +45,7 @@ public NativeGLView(NativeActivity activity) {
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

mController = Controller.getInstance(activity);

try {
MogaHack.init(mController, activity);
Log.i(TAG, "MOGA initialized");
Expand Down
4 changes: 2 additions & 2 deletions android/src/org/ppsspp/ppsspp/NativeSurfaceView.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import android.util.Log;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceView;

import com.bda.controller.Controller;
Expand Down Expand Up @@ -45,8 +47,6 @@ public NativeSurfaceView(NativeActivity activity) {

mController = Controller.getInstance(activity);

// this.getHolder().setFormat(PixelFormat.RGBA_8888);

try {
MogaHack.init(mController, activity);
Log.i(TAG, "MOGA initialized");
Expand Down
2 changes: 2 additions & 0 deletions android/src/org/ppsspp/ppsspp/PpssppActivity.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.ppsspp.ppsspp;

import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.content.Intent;
import android.net.Uri;
Expand Down Expand Up @@ -150,6 +151,7 @@ public String getDebugString(String str) {
}
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
public int openContentUri(String uriString, String mode) {
try {
Uri uri = Uri.parse(uriString);
Expand Down
6 changes: 5 additions & 1 deletion android/src/org/ppsspp/ppsspp/SizeManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,11 @@ public void surfaceCreated(SurfaceHolder holder) {
Log.i(TAG, "Bad orientation detected but ignored" + (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT ? " (sdk version)" : ""));
}

Log.d(TAG, "Surface created. pixelWidth=" + pixelWidth + ", pixelHeight=" + pixelHeight + " holder: " + holder.toString() + " or: " + requestedOr);
Display display = activity.getWindowManager().getDefaultDisplay();

refreshRate = display.getRefreshRate();

Log.d(TAG, "Surface created. pixelWidth=" + pixelWidth + ", pixelHeight=" + pixelHeight + " holder: " + holder.toString() + " or: " + requestedOr + " " + refreshRate + "Hz");
NativeApp.setDisplayParameters(pixelWidth, pixelHeight, (int)densityDpi, refreshRate);
getDesiredBackbufferSize(desiredSize);

Expand Down

0 comments on commit 7762ccd

Please sign in to comment.