Skip to content

Commit 386a660

Browse files
committed
Move layer support detection to the backend
The check for support for composition layers must be done in the backend (OpenXR) which is the one with enough data to decide. We were doing it the other way around, checking which devices did support them and forcing it in the Java side because we knew that would work on the native side. It's much safer and less error prone to do it on the backend. This forces us to make some Java calls asynchronous because we don't know whether the backend has done its checks or not.
1 parent 4788e55 commit 386a660

File tree

12 files changed

+108
-58
lines changed

12 files changed

+108
-58
lines changed

app/src/common/shared/com/igalia/wolvic/VRBrowserActivity.java

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@
112112
import java.util.LinkedList;
113113
import java.util.Map;
114114
import java.util.Objects;
115+
import java.util.OptionalInt;
115116
import java.util.Set;
116117
import java.util.concurrent.ConcurrentHashMap;
117118
import java.util.concurrent.ScheduledFuture;
@@ -270,6 +271,8 @@ public void run() {
270271
private boolean mIsEyeTrackingSupported;
271272
private String mImmersiveParentElementXPath;
272273
private String mImmersiveTargetElementXPath;
274+
private OptionalInt mMaxCompositionLayers = OptionalInt.empty();
275+
private LinkedList<CompositionLayersCallback> mCompositionLayersPendingCallbacks;
273276

274277
private ViewTreeObserver.OnGlobalFocusChangeListener globalFocusListener = new ViewTreeObserver.OnGlobalFocusChangeListener() {
275278
@Override
@@ -343,6 +346,7 @@ protected void onCreate(Bundle savedInstanceState) {
343346
mWebXRListeners = new LinkedList<>();
344347
mBackHandlers = new LinkedList<>();
345348
mBrightnessQueue = new LinkedList<>();
349+
mCompositionLayersPendingCallbacks = new LinkedList<>();
346350
mCurrentBrightness = Pair.create(null, 1.0f);
347351
mWidgets = new ConcurrentHashMap<>();
348352

@@ -1471,12 +1475,6 @@ public void resetWindowsPosition() {
14711475
runOnUiThread(() -> mWindows.resetWindowsPosition());
14721476
}
14731477

1474-
@Keep
1475-
@SuppressWarnings("unused")
1476-
public boolean areLayersEnabled() {
1477-
return SettingsStore.getInstance(this).getLayersEnabled();
1478-
}
1479-
14801478
@Keep
14811479
@SuppressWarnings("unused")
14821480
public String getActiveEnvironment() {
@@ -2293,6 +2291,35 @@ private void changeWindowDistance(float aDelta) {
22932291
mSettings.setWindowDistance(clamped);
22942292
}
22952293

2294+
private boolean supportsCompositionLayers() {
2295+
assert(mMaxCompositionLayers.isPresent());
2296+
return mMaxCompositionLayers.getAsInt() > 1;
2297+
}
2298+
2299+
@Keep
2300+
@SuppressWarnings("unused")
2301+
private void onMaxCompositionLayersAvailable(int aNumLayers) {
2302+
assert(!mMaxCompositionLayers.isPresent());
2303+
mMaxCompositionLayers = OptionalInt.of(aNumLayers);
2304+
Log.i(LOGTAG, "Max composition layers: " + aNumLayers + " so " + (supportsCompositionLayers() ? "enabling" : "disabling") + " layers support");
2305+
runOnUiThread(() -> {
2306+
boolean supportsLayers = supportsCompositionLayers();
2307+
for (CompositionLayersCallback callback : mCompositionLayersPendingCallbacks) {
2308+
callback.onCompositionLayersSupport(supportsLayers);
2309+
}
2310+
mCompositionLayersPendingCallbacks.clear();
2311+
});
2312+
}
2313+
2314+
@Override
2315+
public void areCompositionLayersSupported(@NonNull CompositionLayersCallback callback) {
2316+
if (!mMaxCompositionLayers.isPresent()) {
2317+
mCompositionLayersPendingCallbacks.add(callback);
2318+
return;
2319+
}
2320+
callback.onCompositionLayersSupport(supportsCompositionLayers());
2321+
}
2322+
22962323
private native void addWidgetNative(int aHandle, WidgetPlacement aPlacement);
22972324
private native void updateWidgetNative(int aHandle, WidgetPlacement aPlacement);
22982325
private native void updateVisibleWidgetsNative();

app/src/common/shared/com/igalia/wolvic/browser/SettingsStore.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -698,15 +698,6 @@ public void setMSAALevel(int level) {
698698
editor.apply();
699699
}
700700

701-
public boolean getLayersEnabled() {
702-
if ((DeviceType.isOculusBuild() || DeviceType.isPicoXR()) || DeviceType.isPfdmXR() && !mDisableLayers) {
703-
Log.i(LOGTAG, "Layers are enabled");
704-
return true;
705-
}
706-
Log.i(LOGTAG, "Layers are not supported");
707-
return false;
708-
}
709-
710701
public int getTransparentBorderWidth() {
711702
return 1;
712703
}

app/src/common/shared/com/igalia/wolvic/ui/widgets/KeyboardWidget.java

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -538,20 +538,21 @@ public void dismiss() {
538538
}
539539

540540
public void proxifyLayerIfNeeded(ArrayList<WindowWidget> aWindows) {
541-
if (!SettingsStore.getInstance(getContext()).getLayersEnabled()) {
542-
return;
543-
}
544-
boolean proxify = false;
545-
for (WindowWidget window: aWindows) {
546-
if (window.getPlacement().borderColor != 0) {
547-
proxify = true;
548-
break;
541+
mWidgetManager.areCompositionLayersSupported((boolean enabled) -> {
542+
if (!enabled)
543+
return;
544+
boolean proxify = false;
545+
for (WindowWidget window: aWindows) {
546+
if (window.getPlacement().borderColor != 0) {
547+
proxify = true;
548+
break;
549+
}
549550
}
550-
}
551-
if (mWidgetPlacement.proxifyLayer != proxify) {
552-
mWidgetPlacement.proxifyLayer = proxify;
553-
mWidgetManager.updateWidget(this);
554-
}
551+
if (mWidgetPlacement.proxifyLayer != proxify) {
552+
mWidgetPlacement.proxifyLayer = proxify;
553+
mWidgetManager.updateWidget(this);
554+
}
555+
});
555556
}
556557

557558
private void hideOverlays() {

app/src/common/shared/com/igalia/wolvic/ui/widgets/WidgetManagerDelegate.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ interface EyeTrackingCallback {
3939
void onEyeTrackingPermissionRequest(boolean aPermissionGranted);
4040
}
4141

42+
interface CompositionLayersCallback {
43+
void onCompositionLayersSupport(boolean aSupported);
44+
}
45+
4246
float DEFAULT_DIM_BRIGHTNESS = 0.25f;
4347
float DEFAULT_NO_DIM_BRIGHTNESS = 1.0f;
4448

@@ -152,5 +156,5 @@ enum OriginatorType {WEBSITE, APPLICATION}
152156
boolean isEyeTrackingSupported();
153157
boolean isHandTrackingSupported();
154158
boolean areControllersAvailable();
155-
159+
void areCompositionLayersSupported(@NonNull CompositionLayersCallback callback);
156160
}

app/src/common/shared/com/igalia/wolvic/ui/widgets/WindowWidget.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -375,10 +375,14 @@ public void onResume() {
375375
super.onResume();
376376
if (isVisible() || mIsInVRVideoMode) {
377377
mSession.setActive(true);
378-
if (!SettingsStore.getInstance(getContext()).getLayersEnabled() && !mSession.hasDisplay()) {
379-
// Ensure the Display is correctly recreated.
380-
// See: https://github.com/MozillaReality/FirefoxReality/issues/2880
381-
callSurfaceChanged();
378+
if (!mSession.hasDisplay()) {
379+
mWidgetManager.areCompositionLayersSupported((boolean enabled) -> {
380+
if (enabled) {
381+
// Ensure the Display is correctly recreated.
382+
// See: https://github.com/MozillaReality/FirefoxReality/issues/2880
383+
callSurfaceChanged();
384+
}
385+
});
382386
}
383387
}
384388
}
@@ -430,12 +434,16 @@ public void loadHome() {
430434
}
431435

432436
private void recreateWidgetSurfaceIfNeeded(float prevDensity) {
433-
if (prevDensity != mWidgetPlacement.density || !SettingsStore.getInstance(getContext()).getLayersEnabled())
437+
if (prevDensity != mWidgetPlacement.density)
434438
return;
435439

436-
// If the densities are the same updateWidget won't generate a new surface as the resulting
437-
// texture sizes are equal. We need to force a new surface creation when using layers.
438-
mWidgetManager.recreateWidgetSurface(this);
440+
mWidgetManager.areCompositionLayersSupported((boolean enabled) -> {
441+
if (enabled) {
442+
// If the densities are the same updateWidget won't generate a new surface as the resulting
443+
// texture sizes are equal. We need to force a new surface creation when using layers.
444+
mWidgetManager.recreateWidgetSurface(this);
445+
}
446+
});
439447
}
440448

441449
private void setView(View view, boolean switchSurface, @ViewBrightness int viewBrightness) {

app/src/common/shared/com/igalia/wolvic/ui/widgets/menus/HamburgerMenuWidget.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.igalia.wolvic.ui.widgets.UIWidget;
2727
import com.igalia.wolvic.ui.widgets.WidgetManagerDelegate;
2828
import com.igalia.wolvic.ui.widgets.WidgetPlacement;
29+
import com.igalia.wolvic.ui.widgets.WindowWidget;
2930
import com.igalia.wolvic.utils.AnimationHelper;
3031
import com.igalia.wolvic.utils.ViewUtils;
3132

@@ -41,8 +42,6 @@ public class HamburgerMenuWidget extends UIWidget implements
4142
WidgetManagerDelegate.FocusChangeListener,
4243
ComponentsAdapter.StoreUpdatesListener {
4344

44-
private boolean mProxify = SettingsStore.getInstance(getContext()).getLayersEnabled();
45-
4645
public interface MenuDelegate {
4746
void onSendTab();
4847
void onResize();
@@ -109,10 +108,8 @@ public void onConfigurationChanged(Configuration newConfig) {
109108
updateUI();
110109
}
111110

112-
@Override
113-
public void show(int aShowFlags) {
114-
mWidgetPlacement.proxifyLayer = mProxify;
115-
super.show(aShowFlags);
111+
private void internalShow(boolean proxifyLayer) {
112+
mWidgetPlacement.proxifyLayer = proxifyLayer;
116113

117114
if (mWidgetManager != null) {
118115
mWidgetManager.addFocusChangeListener(this);
@@ -123,6 +120,18 @@ public void show(int aShowFlags) {
123120
AnimationHelper.scaleIn(findViewById(R.id.menuContainer), 100, 0, null);
124121
}
125122

123+
@Override
124+
public void show(int aShowFlags) {
125+
super.show(aShowFlags);
126+
if (mWidgetManager == null) {
127+
internalShow(false);
128+
} else {
129+
mWidgetManager.areCompositionLayersSupported(supported -> {
130+
internalShow(supported);
131+
});
132+
}
133+
}
134+
126135
@Override
127136
public void hide(int aHideFlags) {
128137
hide(aHideFlags, true);

app/src/main/cpp/BrowserWorld.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,7 @@ BrowserWorld::RegisterDeviceDelegate(DeviceDelegatePtr aDelegate) {
946946
m.device->SetControllerDelegate(delegate);
947947
m.device->SetReorientClient(this);
948948
m.gestures = m.device->GetGestureDelegate();
949+
VRBrowser::OnMaxCompositionLayersAvailable(m.device->MaxCompositionLayers());
949950
} else if (previousDevice) {
950951
m.leftCamera = m.rightCamera = nullptr;
951952
m.controllers->Reset();

app/src/main/cpp/DeviceDelegate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ class DeviceDelegate {
140140
virtual bool PopulateTrackedKeyboardInfo(TrackedKeyboardInfo& keyboardInfo) { return false; };
141141
virtual void SetHandTrackingEnabled(bool value) {};
142142
virtual float GetSelectThreshold(int32_t controllerIndex) { return 1.f; };
143+
virtual unsigned MaxCompositionLayers() const { return 1; }
143144

144145
protected:
145146
DeviceDelegate() {}

app/src/main/cpp/VRBrowser.cpp

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,6 @@ const char* const kGetActiveEnvironment = "getActiveEnvironment";
5454
const char* const kGetActiveEnvironmentSignature = "()Ljava/lang/String;";
5555
const char* const kGetPointerColor = "getPointerColor";
5656
const char* const kGetPointerColorSignature = "()I";
57-
const char* const kAreLayersEnabled = "areLayersEnabled";
58-
const char* const kAreLayersEnabledSignature = "()Z";
5957
const char* const kSetDeviceType = "setDeviceType";
6058
const char* const kSetDeviceTypeSignature = "(I)V";
6159
const char* const kHaltActivity = "haltActivity";
@@ -80,6 +78,8 @@ const char* const kOnControllersAvailable = "onControllersAvailable";
8078
const char* const kOnControllersAvailableSignature = "()V";
8179
const char* const kChangeWindowDistance = "changeWindowDistance";
8280
const char* const kChangeWindowDistanceSignature = "(F)V";
81+
const char* const kOnMaxCompositionLayersAvailableName = "onMaxCompositionLayersAvailable";
82+
const char* const kOnMaxCompositionLayersAvailableSignature = "(I)V";
8383

8484
JNIEnv* sEnv = nullptr;
8585
jclass sBrowserClass = nullptr;
@@ -106,7 +106,6 @@ jmethodID sCheckTogglePassthrough = nullptr;
106106
jmethodID sResetWindowsPosition = nullptr;
107107
jmethodID sGetActiveEnvironment = nullptr;
108108
jmethodID sGetPointerColor = nullptr;
109-
jmethodID sAreLayersEnabled = nullptr;
110109
jmethodID sSetDeviceType = nullptr;
111110
jmethodID sHaltActivity = nullptr;
112111
jmethodID sHandlePoorPerformance = nullptr;
@@ -119,6 +118,7 @@ jmethodID sSetEyeTrackingSupported = nullptr;
119118
jmethodID sSetHandTrackingSupported = nullptr;
120119
jmethodID sOnControllersAvailable = nullptr;
121120
jmethodID sChangeWindowDistance = nullptr;
121+
jmethodID sOnMaxCompositionLayersAvailable = nullptr;
122122

123123
} // namespace
124124

@@ -161,7 +161,6 @@ VRBrowser::InitializeJava(JNIEnv* aEnv, jobject aActivity) {
161161
sResetWindowsPosition = FindJNIMethodID(sEnv, sBrowserClass, kResetWindowsPosition, kResetWindowsPositionSignature);
162162
sGetActiveEnvironment = FindJNIMethodID(sEnv, sBrowserClass, kGetActiveEnvironment, kGetActiveEnvironmentSignature);
163163
sGetPointerColor = FindJNIMethodID(sEnv, sBrowserClass, kGetPointerColor, kGetPointerColorSignature);
164-
sAreLayersEnabled = FindJNIMethodID(sEnv, sBrowserClass, kAreLayersEnabled, kAreLayersEnabledSignature);
165164
sSetDeviceType = FindJNIMethodID(sEnv, sBrowserClass, kSetDeviceType, kSetDeviceTypeSignature);
166165
sHaltActivity = FindJNIMethodID(sEnv, sBrowserClass, kHaltActivity, kHaltActivitySignature);
167166
sHandlePoorPerformance = FindJNIMethodID(sEnv, sBrowserClass, kHandlePoorPerformance, kHandlePoorPerformanceSignature);
@@ -174,6 +173,7 @@ VRBrowser::InitializeJava(JNIEnv* aEnv, jobject aActivity) {
174173
sSetHandTrackingSupported = FindJNIMethodID(sEnv, sBrowserClass, kSetHandTrackingSupported, kSetHandTrackingSupportedSignature);
175174
sOnControllersAvailable = FindJNIMethodID(sEnv, sBrowserClass, kOnControllersAvailable, kOnControllersAvailableSignature);
176175
sChangeWindowDistance = FindJNIMethodID(sEnv, sBrowserClass, kChangeWindowDistance, kChangeWindowDistanceSignature);
176+
sOnMaxCompositionLayersAvailable = FindJNIMethodID(sEnv, sBrowserClass, kOnMaxCompositionLayersAvailableName, kOnMaxCompositionLayersAvailableSignature);
177177
}
178178

179179
JNIEnv * VRBrowser::Env()
@@ -216,14 +216,14 @@ VRBrowser::ShutdownJava() {
216216
sResetWindowsPosition = nullptr;
217217
sGetActiveEnvironment = nullptr;
218218
sGetPointerColor = nullptr;
219-
sAreLayersEnabled = nullptr;
220219
sSetDeviceType = nullptr;
221220
sHaltActivity = nullptr;
222221
sOnAppLink = nullptr;
223222
sDisableLayers = nullptr;
224223
sEnv = nullptr;
225224
sAppendAppNotesToCrashReport = nullptr;
226225
sChangeWindowDistance = nullptr;
226+
sOnMaxCompositionLayersAvailable = nullptr;
227227
}
228228

229229
void
@@ -418,15 +418,6 @@ VRBrowser::GetPointerColor() {
418418
return (int32_t )jHexColor;
419419
}
420420

421-
bool
422-
VRBrowser::AreLayersEnabled() {
423-
if (!ValidateMethodID(sEnv, sActivity, sAreLayersEnabled, __FUNCTION__)) { return false; }
424-
jboolean enabled = sEnv->CallBooleanMethod(sActivity, sAreLayersEnabled);
425-
CheckJNIException(sEnv, __FUNCTION__);
426-
427-
return enabled;
428-
}
429-
430421
void
431422
VRBrowser::SetDeviceType(const jint aType) {
432423
if (!ValidateMethodID(sEnv, sActivity, sSetDeviceType, __FUNCTION__)) { return; }
@@ -517,4 +508,11 @@ VRBrowser::ChangeWindowDistance(jfloat aDelta) {
517508
CheckJNIException(sEnv, __FUNCTION__);
518509
}
519510

511+
void
512+
VRBrowser::OnMaxCompositionLayersAvailable(jint aNumLayers) {
513+
if (!ValidateMethodID(sEnv, sActivity, sOnMaxCompositionLayersAvailable, __FUNCTION__)) { return; }
514+
sEnv->CallVoidMethod(sActivity, sOnMaxCompositionLayersAvailable, aNumLayers);
515+
CheckJNIException(sEnv, __FUNCTION__);
516+
}
517+
520518
} // namespace crow

app/src/main/cpp/VRBrowser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ void SetEyeTrackingSupported(bool aIsSupported);
5454
void SetHandTrackingSupported(bool aIsSupported);
5555
void OnControllersAvailable();
5656
void ChangeWindowDistance(jfloat aDelta);
57+
void OnMaxCompositionLayersAvailable(jint aNumLayers);
5758
} // namespace VRBrowser;
5859

5960
} // namespace crow

0 commit comments

Comments
 (0)