Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions app/src/main/java/com/limelight/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,14 @@ public class Game extends AppCompatActivity implements SurfaceHolder.Callback,
private View performanceOverlayView;

private TextView performanceOverlayLite;

private TextView performanceOverlayMini;

private TextView performanceOverlayBig;

private TextView androidTvForceGpuComposition;
private boolean gpuCompositionToggle = false;

private MediaCodecDecoderRenderer decoderRenderer;
private boolean reportedCrash;

Expand Down Expand Up @@ -521,8 +526,12 @@ else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {

performanceOverlayLite = findViewById(R.id.performanceOverlayLite);

performanceOverlayMini = findViewById(R.id.performanceOverlayMini);

performanceOverlayBig = findViewById(R.id.performanceOverlayBig);

androidTvForceGpuComposition = findViewById(R.id.androidTvForceGpuComposition);

inputCaptureProvider = InputCaptureManager.getInputCaptureProvider(this, this);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Expand Down Expand Up @@ -633,14 +642,21 @@ public boolean onCapturedPointer(View view, MotionEvent motionEvent) {
// Check if the user has enabled performance stats overlay
if (prefConfig.enablePerfOverlay) {
performanceOverlayView.setVisibility(View.VISIBLE);

if (prefConfig.enablePerfOverlayLite) {
performanceOverlayLite.setVisibility(View.VISIBLE);
if(prefConfig.enablePerfOverlayLiteDialog){
performanceOverlayLite.setOnClickListener(v -> showGameMenu(null));
}
} else if (prefConfig.enablePerfOverlayMini) {
performanceOverlayMini.setVisibility(View.VISIBLE);
if(prefConfig.enablePerfOverlayMiniDialog){
performanceOverlayMini.setOnClickListener(v -> showGameMenu(null));
}
} else {
performanceOverlayBig.setVisibility(View.VISIBLE);
}

if (prefConfig.enablePerfOverlayBottom) {
//performanceOverlayView.getLayoutParams().layout_gravity = Gravity.BOTTOM;
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) performanceOverlayView.getLayoutParams();
Expand All @@ -649,6 +665,15 @@ public boolean onCapturedPointer(View view, MotionEvent motionEvent) {
}
}

// Configure Force GPU Composition for Android TV
if (androidTvForceGpuComposition != null) {
if (prefConfig.enableAndroidTvForceGpuComposition) {
androidTvForceGpuComposition.setVisibility(View.VISIBLE);
} else {
androidTvForceGpuComposition.setVisibility(View.GONE);
}
}

decoderRenderer = new MediaCodecDecoderRenderer(
this,
prefConfig,
Expand Down Expand Up @@ -3934,9 +3959,17 @@ public void onPerfUpdate(final String text) {
public void run() {
if(prefConfig.enablePerfOverlayLite){
performanceOverlayLite.setText(text);
}else if(prefConfig.enablePerfOverlayMini){
performanceOverlayMini.setText(text);
}else{
performanceOverlayBig.setText(text);
}

// Toggle GPU composition on Android TV by alternating an invisible character
if (androidTvForceGpuComposition != null && prefConfig.enableAndroidTvForceGpuComposition) {
gpuCompositionToggle = !gpuCompositionToggle;
androidTvForceGpuComposition.setText(gpuCompositionToggle ? "·" : ".");
}
}
});
}
Expand Down Expand Up @@ -4198,6 +4231,8 @@ public void toggleHUD() {
performanceOverlayView.setVisibility(View.VISIBLE);
if(prefConfig.enablePerfOverlayLite){
performanceOverlayLite.setVisibility(View.VISIBLE);
}else if(prefConfig.enablePerfOverlayMini){
performanceOverlayMini.setVisibility(View.VISIBLE);
}else{
performanceOverlayBig.setVisibility(View.VISIBLE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1791,7 +1791,48 @@ public int submitDecodeUnit(byte[] decodeUnitData, int decodeUnitLength, int dec
float decodeTimeMs = (float)lastTwo.decoderTimeMs / lastTwo.totalFramesReceived;
long rttInfo = MoonBridge.getEstimatedRttInfo();
StringBuilder sb = new StringBuilder();
if(prefs.enablePerfOverlayLite){
if(prefs.enablePerfOverlayMini){
if(TrafficStatsHelper.getPackageRxBytes(Process.myUid()) != TrafficStats.UNSUPPORTED){
long netData=TrafficStatsHelper.getPackageRxBytes(Process.myUid())+TrafficStatsHelper.getPackageTxBytes(Process.myUid());
if(lastNetDataNum!=0){
float realtimeNetData=(netData-lastNetDataNum)/1024f;
if(realtimeNetData>=1000){
sb.append("BW: ").append(String.format("%.1f", realtimeNetData/1024f)).append(" M/s\n");
}else{
sb.append("BW: ").append(String.format("%.1f", realtimeNetData)).append(" K/s\n");
}
}
lastNetDataNum=netData;
}
sb.append("PL: ").append(String.format("%.0f", (float)lastTwo.framesLost / lastTwo.totalFrames * 100)).append("%\n");
sb.append("Net: ").append((int)(rttInfo >> 32)).append("ms | Dec: ").append(String.format("%.1f", decodeTimeMs)).append("ms\n");
sb.append(String.format("%.2f", fps.totalFps)).append(" FPS");

} else if(prefs.enablePerfOverlayLite){
if(TrafficStatsHelper.getPackageRxBytes(Process.myUid()) != TrafficStats.UNSUPPORTED){
long netData=TrafficStatsHelper.getPackageRxBytes(Process.myUid())+TrafficStatsHelper.getPackageTxBytes(Process.myUid());
if(lastNetDataNum!=0){
sb.append(context.getString(R.string.perf_overlay_lite_bandwidth) + ": ");
float realtimeNetData=(netData-lastNetDataNum)/1024f;
if(realtimeNetData>=1000){
sb.append(String.format("%.2f", realtimeNetData/1024f) +"M/s\t ");
}else{
sb.append(String.format("%.2f", realtimeNetData) +"K/s\t ");
}
}
lastNetDataNum=netData;
}
// sb.append("分辨率:");
// sb.append(initialWidth + "x" + initialHeight);
sb.append(context.getString(R.string.perf_overlay_lite_network_decoding_delay) + ": ");
sb.append(context.getString(R.string.perf_overlay_lite_net,(int)(rttInfo >> 32)));
sb.append(" / ");
sb.append(context.getString(R.string.perf_overlay_lite_dectime,decodeTimeMs));
sb.append("\t");
sb.append(context.getString(R.string.perf_overlay_lite_packet_loss) + ": ");
sb.append(context.getString(R.string.perf_overlay_lite_netdrops,(float)lastTwo.framesLost / lastTwo.totalFrames * 100));
sb.append("\t FPS:");
sb.append(context.getString(R.string.perf_overlay_lite_fps, fps.totalFps));
if(TrafficStatsHelper.getPackageRxBytes(Process.myUid()) != TrafficStats.UNSUPPORTED){
long netData=TrafficStatsHelper.getPackageRxBytes(Process.myUid())+TrafficStatsHelper.getPackageTxBytes(Process.myUid());
if(lastNetDataNum!=0){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,14 @@ public enum AnalogStickForScrolling {

public boolean enablePerfOverlayLiteDialog;

public boolean enablePerfOverlayMini;

public boolean enablePerfOverlayMiniDialog;

public boolean enablePerfOverlayBottom;

public boolean enableAndroidTvForceGpuComposition;

public boolean enableLatencyToast;
public boolean enableBackMenu;
public boolean enableFloatingButton;
Expand Down Expand Up @@ -923,7 +929,9 @@ else if (audioConfig.equals("51")) {
config.enablePerfOverlay = prefs.getBoolean(ENABLE_PERF_OVERLAY_STRING, DEFAULT_ENABLE_PERF_OVERLAY);
config.enablePerfLogging = prefs.getBoolean(ENABLE_PERF_LOGGING, DEFAULT_ENABLE_PERF_LOGGING);
config.enablePerfOverlayLite = prefs.getBoolean("checkbox_enable_perf_overlay_lite",DEFAULT_ENABLE_PERF_OVERLAY);
config.enablePerfOverlayMini = prefs.getBoolean("checkbox_enable_perf_overlay_mini",DEFAULT_ENABLE_PERF_OVERLAY);
config.enablePerfOverlayBottom = prefs.getBoolean("checkbox_enable_perf_overlay_bottom",DEFAULT_PERF_OVERLAY_BOTTOM);
config.enableAndroidTvForceGpuComposition = prefs.getBoolean("checkbox_enable_android_tv_force_gpu_composition", false);
config.bindAllUsb = prefs.getBoolean(BIND_ALL_USB_STRING, DEFAULT_BIND_ALL_USB);
config.mouseEmulation = prefs.getBoolean(MOUSE_EMULATION_STRING, DEFAULT_MOUSE_EMULATION);
config.mouseNavButtons = prefs.getBoolean(MOUSE_NAV_BUTTONS_STRING, DEFAULT_MOUSE_NAV_BUTTONS);
Expand Down Expand Up @@ -981,7 +989,7 @@ else if (audioConfig.equals("51")) {

config.enableMultiTouchGestures = prefs.getBoolean("checkbox_multi_touch_gestures", false);


config.enablePerfOverlayLiteDialog=prefs.getBoolean("checkbox_enable_perf_overlay_lite_dialog",false);

config.disableDefaultExtraKeys =prefs.getBoolean("checkbox_enable_clear_default_special_button", false);
Expand Down
30 changes: 30 additions & 0 deletions app/src/main/java/com/limelight/preferences/StreamSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,36 @@ public boolean onPreferenceClick(@NonNull Preference preference) {
}
});
}

// Mutual exclusion between Lite and Mini overlay modes
CheckBoxPreference litePref = findPreference("checkbox_enable_perf_overlay_lite");
CheckBoxPreference miniPref = findPreference("checkbox_enable_perf_overlay_mini");

if (litePref != null && miniPref != null) {
litePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
Boolean isEnabled = (Boolean) newValue;
if (isEnabled && miniPref.isChecked()) {
// Disable mini when enabling lite
miniPref.setChecked(false);
}
return true;
}
});

miniPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
Boolean isEnabled = (Boolean) newValue;
if (isEnabled && litePref.isChecked()) {
// Disable lite when enabling mini
litePref.setChecked(false);
}
return true;
}
});
}
}

private void removeEntryFromListAndSetValue(String resolutionPrefString, String entryToRemove, String nextDefault) {
Expand Down
34 changes: 34 additions & 0 deletions app/src/main/res/layout/activity_game.xml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,40 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

<TextView
android:id="@+id/performanceOverlayMini"
tools:text="BW: 109M/s PL: 0% Net: 7ms | Dec: 109ms XX.XX FPS"
android:textSize="8sp"
android:layout_marginTop="10dp"
android:layout_marginStart="10dp"
android:background="@android:color/transparent"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:paddingTop="1dp"
android:paddingBottom="1dp"
android:visibility="gone"
android:textColor="#CCFFFFFF"
android:layout_gravity="start|top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

<TextView
android:id="@+id/androidTvForceGpuComposition"
tools:text="Force GPU Composition"
android:textSize="1sp"
android:layout_marginTop="1dp"
android:layout_marginStart="1dp"
android:background="@android:color/transparent"
android:paddingLeft="1dp"
android:paddingRight="1dp"
android:paddingTop="1dp"
android:paddingBottom="1dp"
android:visibility="visible"
android:textColor="#FFFFFF"
android:layout_gravity="start|top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

</LinearLayout>

<!-- Floating Menu Button -->
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,8 @@
<string name="summary_checkbox_onscreen_style_official">If you still like the old style of official virtual gamepad buttons, you can select this option.\nButton shapes can be square if you selected the bottom virtual button [Normal buttons are square buttons]</string>
<string name="title_checkbox_enable_perf_overlay_lite">Enable Lite mode</string>
<string name="summary_checkbox_enable_perf_overlay_lite">Display simplified performance information: Network Speed / Latency / Decode / Packet Loss Rate / FPS</string>
<string name="title_checkbox_enable_perf_overlay_mini">Enable Mini mode</string>
<string name="summary_checkbox_enable_perf_overlay_mini">Display simplified performance mini information</string>
<string name="title_checkbox_enable_perf_logging">Enable Performance Logging</string>
<string name="summary_checkbox_enable_perf_logging">"Stores performance data per configuration. (Offline only) "</string>
<string name="title_checkbox_enable_perf_overlay_lite_dialog">Lite mode click to pop up quick options</string>
Expand Down Expand Up @@ -698,6 +700,8 @@
<string name="summary_checkbox_remember_zoom_pan">Save changes to zoom and pan position between sessions</string>
<string name="title_checkbox_enable_perf_overlay_bottom">Move overlay to bottom</string>
<string name="summary_checkbox_enable_perf_overlay_bottom">Useful when Display in Top Center and Lite mode are enabled during non-native resolution streaming.</string>
<string name="title_checkbox_enable_android_tv_force_gpu_composition">Force GPU Composition (Android TV)</string>
<string name="summary_checkbox_enable_android_tv_force_gpu_composition">Fixes frame sync issues on Android TV by forcing GPU composition. Enable if video playback has stuttering or frame drops.</string>
<string name="title_edit_profile">Edit Profile</string>
<string name="profile_manager_new_profile">New Profile</string>
<string name="profile_manager_profile_not_found">Profile not found</string>
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/res/xml/preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,13 @@
android:summary="@string/summary_checkbox_enable_perf_overlay_lite_dialog"
android:title="@string/title_checkbox_enable_perf_overlay_lite_dialog"
app:iconSpaceReserved="false" />
<CheckBoxPreference
android:defaultValue="false"
android:dependency="checkbox_enable_perf_overlay"
android:key="checkbox_enable_perf_overlay_mini"
android:summary="@string/summary_checkbox_enable_perf_overlay_mini"
android:title="@string/title_checkbox_enable_perf_overlay_mini"
app:iconSpaceReserved="false" />
<CheckBoxPreference
android:defaultValue="false"
android:dependency="checkbox_enable_perf_overlay"
Expand Down Expand Up @@ -973,6 +980,12 @@
android:summary="@string/summary_prevent_packet_loss"
android:title="@string/title_prevent_packet_loss"
app:iconSpaceReserved="false" />
<CheckBoxPreference
android:defaultValue="false"
android:key="checkbox_enable_android_tv_force_gpu_composition"
android:summary="@string/summary_checkbox_enable_android_tv_force_gpu_composition"
android:title="@string/title_checkbox_enable_android_tv_force_gpu_composition"
app:iconSpaceReserved="false" />
</PreferenceCategory>

<PreferenceCategory
Expand Down