Skip to content

Commit

Permalink
[Pico] Add a OS version check
Browse files Browse the repository at this point in the history
Pico OpenXR runtime had several issues over the time. We had to add
workarounds here and there to support those OS versions. As time passes
by those workarounds just make the code more complex to maintain
without any real benefit (as it affects really old versions of the OS).

After this change Pico OS versions < v5.7.1 are no longer supported
and Wolvic will refuse to start.

This allows us to remove a lot of code workarounding runtime bugs
including the legacy hand mesh renderer using spheres.
  • Loading branch information
svillar committed Sep 17, 2024
1 parent 9ccbdf5 commit ab6d436
Show file tree
Hide file tree
Showing 10 changed files with 38 additions and 143 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,6 @@ public void run() {
static final long RESET_CRASH_COUNT_DELAY = 5000;
static final int UPDATE_NATIVE_WIDGETS_DELAY = 50; // milliseconds

// Passthrough was enabled on Pico version 5.7.1, via XR_FB_passthrough extension
static final String kPicoVersionPassthroughUpdate = "5.7.1";

static final String LOGTAG = SystemUtils.createLogtag(VRBrowserActivity.class);
ConcurrentHashMap<Integer, Widget> mWidgets;
private int mWidgetHandleIndex = 1;
Expand Down Expand Up @@ -2015,8 +2012,7 @@ public boolean isPassthroughEnabled() {
}
@Override
public boolean isPassthroughSupported() {
return DeviceType.isOculusBuild() || DeviceType.isLynx() || DeviceType.isSnapdragonSpaces() ||
(DeviceType.isPicoXR() && Build.ID.compareTo(kPicoVersionPassthroughUpdate) >= 0);
return DeviceType.isOculusBuild() || DeviceType.isLynx() || DeviceType.isSnapdragonSpaces() || DeviceType.isPicoXR();
}

@Override
Expand Down
69 changes: 0 additions & 69 deletions app/src/main/cpp/HandMeshRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,75 +38,6 @@ vrb::RenderStatePtr GetHandMeshDefaultRenderState(vrb::CreationContextPtr create
return state;
}

// HandMeshRendererSpheres

struct HandMeshSpheres {
vrb::TogglePtr toggle;
std::vector<vrb::TransformPtr> sphereTransforms;
};

struct HandMeshRendererSpheres::State {
std::vector<HandMeshSpheres> handMeshState;
};

HandMeshRendererSpheres::HandMeshRendererSpheres(State& aState, vrb::CreationContextPtr& aContext)
: m(aState) {
context = aContext;
}

HandMeshRendererPtr HandMeshRendererSpheres::Create(vrb::CreationContextPtr& aContext) {
return std::make_unique<vrb::ConcreteClass<HandMeshRendererSpheres, HandMeshRendererSpheres::State> >(aContext);
}

void HandMeshRendererSpheres::Update(const uint32_t aControllerIndex, const std::vector<vrb::Matrix>& handJointTransforms,
const vrb::GroupPtr& aRoot, HandMeshBufferPtr& buffer, const bool aEnabled, const bool leftHanded) {
assert(!buffer);

if (aControllerIndex >= m.handMeshState.size())
m.handMeshState.resize(aControllerIndex + 1);
auto& handMesh = m.handMeshState.at(aControllerIndex);

// We need to call ToggleAll() even if aEnabled is false, to be able to hide the
// hand mesh.
if (handMesh.toggle)
handMesh.toggle->ToggleAll(aEnabled);

if (!aEnabled)
return;

// Lazily create toggle and spheres' geometry and transform nodes.
if (!handMesh.toggle) {
vrb::CreationContextPtr create = context.lock();
handMesh.toggle = vrb::Toggle::Create(create);

assert(handJointTransforms.size() > 0);

auto state = GetHandMeshDefaultRenderState(create);

float radius = 0.65;
vrb::GeometryPtr sphere = DeviceUtils::GetSphereGeometry(create, 36, radius);
sphere->SetRenderState(state);

handMesh.sphereTransforms.resize(handJointTransforms.size());
for (uint32_t i = 0; i < handMesh.sphereTransforms.size(); i++) {
vrb::TransformPtr transform = vrb::Transform::Create(create);
transform->AddNode(sphere);
handMesh.toggle->AddNode(transform);
handMesh.sphereTransforms[i] = transform;
}
}

// Check that the toggle node has been added to the scene graph
std::vector<vrb::GroupPtr> parents;
handMesh.toggle->GetParents(parents);
if (parents.size() == 0)
aRoot->AddNode(handMesh.toggle);

assert(handMesh.sphereTransforms.size() == handJointTransforms.size());
for (int i = 0; i < handMesh.sphereTransforms.size(); i++)
handMesh.sphereTransforms[i]->SetTransform(handJointTransforms[i]);
}

// HandMeshRendererGeometry

struct HandMeshGeometry {
Expand Down
15 changes: 0 additions & 15 deletions app/src/main/cpp/HandMeshRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,6 @@ class HandMeshRenderer {
};


// HandMeshRendererSpheres

class HandMeshRendererSpheres: public HandMeshRenderer {
protected:
struct State;
State& m;
HandMeshRendererSpheres(State&, vrb::CreationContextPtr&);
public:
static HandMeshRendererPtr Create(vrb::CreationContextPtr&);
private:
void Update(const uint32_t aControllerIndex, const std::vector<vrb::Matrix>& handJointTransforms,
const vrb::GroupPtr& aRoot, HandMeshBufferPtr& aBuffer, const bool aEnabled, const bool leftHanded) override;
};


// HandMeshRendererSkinned

struct HandMeshSkinned;
Expand Down
7 changes: 0 additions & 7 deletions app/src/openxr/cpp/DeviceDelegateOpenXR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1672,13 +1672,6 @@ DeviceDelegateOpenXR::EnterVR(const crow::BrowserEGLContext& aEGLContext) {
if (m.handMeshProperties) {
m.handMeshRenderer = HandMeshRendererGeometry::Create(create);
m.input->SetHandMeshBufferSizes(m.handMeshProperties->indexCount, m.handMeshProperties->vertexCount);
} else {
#if defined(PICOXR)
// Due to unreliable hand-tracking orientation data on Pico devices running system
// versions earlier than 5.7.1, we use the Spheres strategy.
if (CompareBuildIdString(kPicoVersionHandTrackingUpdate))
m.handMeshRenderer = HandMeshRendererSpheres::Create(create);
#endif
}

if (!m.handMeshRenderer)
Expand Down
5 changes: 0 additions & 5 deletions app/src/openxr/cpp/OpenXRGestureManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@ OpenXRGestureManager::handFacesHead(const vrb::Matrix &hand, const vrb::Matrix &
// For the hand we take the Y axis because that corresponds to head's Z axis when
// the hand is in upright position facing head (the gesture we want to detect).
auto handDirection = hand.MultiplyDirection({0, 1, 0}).Normalize();
#ifdef PICOXR
// Axis are inverted in Pico system versions prior to 5.7.1
if (CompareBuildIdString(kPicoVersionHandTrackingUpdate))
handDirection = hand.MultiplyDirection({0, 0, -1});
#endif
auto headDirection = head.MultiplyDirection({0, 0, -1}).Normalize();

// First check that vector directions align
Expand Down
8 changes: 0 additions & 8 deletions app/src/openxr/cpp/OpenXRHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,6 @@ namespace crow {
const vrb::Vector kAverageHeight(0.0f, 1.7f, 0.0f);
#endif

// Hand tracking was thoroughly updated on Pico version 5.7.1
static const std::string kPicoVersionHandTrackingUpdate = "5.7.1";

inline bool CompareBuildIdString(const std::string str) {
char buildId[128];
return CompareSemanticVersionStrings(GetBuildIdString(buildId), str);
}

inline std::string GetXrVersionString(XrVersion ver) {
return Fmt("%d.%d.%d", XR_VERSION_MAJOR(ver), XR_VERSION_MINOR(ver), XR_VERSION_PATCH(ver));
}
Expand Down
23 changes: 0 additions & 23 deletions app/src/openxr/cpp/OpenXRInputSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -633,21 +633,6 @@ OpenXRInputSource::PopulateHandJointLocations(device::RenderMode renderMode, std
jointTransforms[i] = transform;
jointRadii[i] = mHandJoints[i].radius;
}
#if defined(PICOXR)
// Scale joints according to their radius (for rendering). This is currently only
// relevant on Pico with system version earlier than 5.7.1, where we are using spheres
// to render the hands instead of a proper hand model due to incorrect joint orientation.
if (CompareBuildIdString(kPicoVersionHandTrackingUpdate)) {
for (int i = 0; i < mHandJoints.size(); i++) {
if (IsHandJointPositionValid((XrHandJointEXT) i, mHandJoints)) {
float radius = mHandJoints[i].radius;
vrb::Matrix scale = vrb::Matrix::Identity().ScaleInPlace(
vrb::Vector(radius, radius, radius));
jointTransforms[i].PostMultiplyInPlace(scale);
}
}
}
#endif
}

void OpenXRInputSource::EmulateControllerFromHand(device::RenderMode renderMode, XrTime predictedDisplayTime, const vrb::Matrix& head, const vrb::Matrix& handJointForAim, DeviceDelegate::PointerMode pointerMode, bool usingEyeTracking, ControllerDelegate& delegate)
Expand Down Expand Up @@ -717,14 +702,6 @@ void OpenXRInputSource::EmulateControllerFromHand(device::RenderMode renderMode,
correctionAngle);
pointerTransform = pointerTransform.PostMultiply(correctionMatrix);
}
#elif defined(PICOXR)
// On Pico, this only affects system versions earlier than 5.7.1
if (CompareBuildIdString(kPicoVersionHandTrackingUpdate)) {
float correctionAngle = -M_PI_2;
pointerTransform
.PostMultiplyInPlace(vrb::Matrix::Rotation(vrb::Vector(0.0, 1.0, 0.0),correctionAngle)
.PostMultiply(vrb::Matrix::Rotation(vrb::Vector(0.0, 0.0, 1.0), correctionAngle)));
}
#endif

device::CapabilityFlags flags = device::Orientation | device::Position;
Expand Down
8 changes: 0 additions & 8 deletions app/src/openxr/cpp/OpenXRLayers.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,14 +189,6 @@ class OpenXRLayerBase : public OpenXRLayer {
info.width = width;
info.height = height;
bool shouldZeroInitialize = aSurfaceType == VRLayerSurface::SurfaceType::AndroidSurface;
#if defined(PICOXR)
// Circumvent a bug in the pico OpenXR runtime in versions below 5.4.0.
char buildId[128] = {0};
if (CompareSemanticVersionStrings(GetBuildIdString(buildId), "5.4.0")) {
// System version is < 5.4.0
shouldZeroInitialize = false;
}
#endif
if (shouldZeroInitialize) {
// These members must be zero
// See https://www.khronos.org/registry/OpenXR/specs/1.0/man/html/xrCreateSwapchainAndroidSurfaceKHR.html#XR_KHR_android_surface_swapchain
Expand Down
2 changes: 1 addition & 1 deletion app/src/picoxr/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
<application android:requestLegacyExternalStorage="true">
<activity android:name=".VRBrowserActivity">
<meta-data android:name="android.app.lib_name" android:value="native-lib" />
<meta-data android:name="pvr.app.type" android:value="vr" />
</activity>
<meta-data android:name="pvr.app.type" android:value="vr" />
<meta-data android:name="handtracking" android:value="1" />
<meta-data android:name="picovr.software.eye_tracking" android:value="true" />
</application>
Expand Down
38 changes: 36 additions & 2 deletions app/src/picoxr/java/com/igalia/wolvic/PlatformSystemCheck.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,44 @@
package com.igalia.wolvic;

import android.util.Log;

import com.igalia.wolvic.utils.SystemUtils;

public class PlatformSystemCheck extends SystemCheck {
private static final String PICO_OS_VERSION_PROPERTY = "ro.build.display.id";
private static final int MIN_PICO_OS_MAJOR_VERSION = 5;
private static final int MIN_PICO_OS_MINOR_VERSION = 7;
private static final int MIN_PICO_OS_PATCH_VERSION = 1;
private static final String LOGTAG = SystemUtils.createLogtag(PlatformSystemCheck.class);

/**
* Compares two version strings in the form x.y.z where x, y, and z are integers.
* @return a negative integer, zero, or a positive integer as the first version
* is less than, equal to, or greater than the second version.
*/
private int compare(String str1, String str2) {
String[] parts1 = str1.split("\\.");
String[] parts2 = str2.split("\\.");

for (int i = 0; i < Math.min(parts1.length, parts2.length); i++) {
int num1 = Integer.parseInt(parts1[i]);
int num2 = Integer.parseInt(parts2[i]);

if (num1 != num2)
return num1 - num2;
}
return parts1.length - parts2.length;
}

@Override
public boolean isOSVersionCompatible() { return true; }
public boolean isOSVersionCompatible() {
String osVersion = getSystemProperty(PICO_OS_VERSION_PROPERTY);
Log.i(LOGTAG, "Checking that OS version is at least " + minSupportedVersion() + " (found " + osVersion + ")");
return compare(osVersion, minSupportedVersion()) >= 0;
}

@Override
public String minSupportedVersion() { return ""; }
public String minSupportedVersion() {
return MIN_PICO_OS_MAJOR_VERSION + "." + MIN_PICO_OS_MINOR_VERSION + "." + MIN_PICO_OS_PATCH_VERSION;
}
}

0 comments on commit ab6d436

Please sign in to comment.