0

Restrict OpenXr features by mode

For the time being, we want to restrict the traditionally AR features to
only be enabled during immersive-ar sessions. We will investigate
removing this restriction, but there's some discussions to be had with
the permissions team due to the different strings shown to the user.

Bug: 40904930
Change-Id: I7be6a32bc7b63fa450a079bf34fddfd5f32de167
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5478412
Commit-Queue: Alexander Cooper <alcooper@chromium.org>
Reviewed-by: Brandon Jones <bajones@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1291940}
This commit is contained in:
Alexander Cooper
2024-04-24 16:57:56 +00:00
committed by Chromium LUCI CQ
parent bd248c5d3a
commit 9fccfa9793
5 changed files with 66 additions and 15 deletions

@ -14,6 +14,7 @@
#include "build/build_config.h"
#include "device/vr/openxr/openxr_api_wrapper.h"
#include "device/vr/openxr/openxr_render_loop.h"
#include "device/vr/openxr/openxr_util.h"
#include "device/vr/public/cpp/features.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/openxr/src/include/openxr/openxr.h"
@ -36,22 +37,26 @@ const std::vector<mojom::XRSessionFeature>& GetSupportedFeatures() {
}
bool AreAllRequiredFeaturesSupported(
const mojom::XRSessionMode mode,
const std::vector<mojom::XRSessionFeature>& required_features,
const OpenXrExtensionHelper& extension_helper) {
return base::ranges::all_of(
required_features,
[&extension_helper](const mojom::XRSessionFeature& feature) {
// This function returns true for features that are supported entirely
// by the core spec. We rely on the Browser process pre-filtering and
// not passing us any features that we haven't already indicated that
// we could support, which is the union of core spec features and things
// that could theoretically be supported depending on enabled
// extensions (which we're now checking if they're actually supported,
// since we need to create an instance to confirm that).
return extension_helper.IsFeatureSupported(feature);
[&extension_helper, mode](const mojom::XRSessionFeature& feature) {
// First we check if we will allow the feature to be supported in the
// mode that has been requested; before querying if the feature can
// actually be supported by the current runtime.
// The extension helper returns true for features that are supported
// entirely by the core spec. We rely on the Browser process
// pre-filtering and not passing us any features that we haven't already
// indicated that we could support, which is the union of core spec
// features and things that could theoretically be supported depending
// on enabled extensions (which we're now checking if they're actually
// supported,since we need to create an instance to confirm that).
return IsFeatureSupportedForMode(feature, mode) &&
extension_helper.IsFeatureSupported(feature);
});
}
} // namespace
OpenXrDevice::OpenXrDevice(
@ -141,8 +146,8 @@ void OpenXrDevice::OnCreateInstanceResult(
extension_helper_ = std::make_unique<OpenXrExtensionHelper>(
instance_, platform_helper_->GetExtensionEnumeration());
if (!AreAllRequiredFeaturesSupported(options->required_features,
*extension_helper_)) {
if (!AreAllRequiredFeaturesSupported(
options->mode, options->required_features, *extension_helper_)) {
DVLOG(1) << __func__ << " Missing a required feature";
// Reject session request, and call ForceEndSession to ensure that we clean
// up any objects that were already created.

@ -19,6 +19,7 @@
#include "device/vr/openxr/exit_xr_present_reason.h"
#include "device/vr/openxr/openxr_api_wrapper.h"
#include "device/vr/openxr/openxr_input_helper.h"
#include "device/vr/openxr/openxr_util.h"
#include "device/vr/util/stage_utils.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
@ -208,7 +209,8 @@ void OpenXrRenderLoop::RequestSession(
frame_data_receiver_.reset();
request_session_callback_ =
base::BindPostTask(main_thread_task_runner_, std::move(callback));
EnableSupportedFeatures(options->required_features,
EnableSupportedFeatures(options->mode, options->required_features,
options->optional_features);
StartRuntime(std::move(on_visibility_state_changed), std::move(options));
@ -789,6 +791,7 @@ void OpenXrRenderLoop::StopRuntime() {
}
void OpenXrRenderLoop::EnableSupportedFeatures(
device::mojom::XRSessionMode mode,
const std::vector<device::mojom::XRSessionFeature>& required_features,
const std::vector<device::mojom::XRSessionFeature>& optional_features) {
enabled_features_.clear();
@ -809,8 +812,9 @@ void OpenXrRenderLoop::EnableSupportedFeatures(
base::ranges::copy_if(
optional_features,
std::inserter(enabled_features_, enabled_features_.begin()),
[this](device::mojom::XRSessionFeature feature) {
return extension_helper_->IsFeatureSupported(feature);
[this, mode](device::mojom::XRSessionFeature feature) {
return IsFeatureSupportedForMode(feature, mode) &&
extension_helper_->IsFeatureSupported(feature);
});
}

@ -207,6 +207,7 @@ class OpenXrRenderLoop : public XRThread,
bool HasSessionEnded();
bool SubmitCompositedFrame();
void EnableSupportedFeatures(
device::mojom::XRSessionMode mode,
const std::vector<device::mojom::XRSessionFeature>& requiredFeatures,
const std::vector<device::mojom::XRSessionFeature>& optionalFeatures);

@ -57,4 +57,41 @@ bool IsPoseValid(XrSpaceLocationFlags locationFlags) {
return (locationFlags & PoseValidFlags) == PoseValidFlags;
}
bool IsArOnlyFeature(device::mojom::XRSessionFeature feature) {
switch (feature) {
case device::mojom::XRSessionFeature::REF_SPACE_VIEWER:
case device::mojom::XRSessionFeature::REF_SPACE_LOCAL:
case device::mojom::XRSessionFeature::REF_SPACE_LOCAL_FLOOR:
case device::mojom::XRSessionFeature::REF_SPACE_BOUNDED_FLOOR:
case device::mojom::XRSessionFeature::REF_SPACE_UNBOUNDED:
case device::mojom::XRSessionFeature::LAYERS:
case device::mojom::XRSessionFeature::HAND_INPUT:
case device::mojom::XRSessionFeature::SECONDARY_VIEWS:
return false;
case device::mojom::XRSessionFeature::DOM_OVERLAY:
case device::mojom::XRSessionFeature::HIT_TEST:
case device::mojom::XRSessionFeature::LIGHT_ESTIMATION:
case device::mojom::XRSessionFeature::ANCHORS:
case device::mojom::XRSessionFeature::CAMERA_ACCESS:
case device::mojom::XRSessionFeature::PLANE_DETECTION:
case device::mojom::XRSessionFeature::DEPTH:
case device::mojom::XRSessionFeature::IMAGE_TRACKING:
case device::mojom::XRSessionFeature::FRONT_FACING:
return true;
}
}
bool IsFeatureSupportedForMode(device::mojom::XRSessionFeature feature,
device::mojom::XRSessionMode mode) {
// OpenXR doesn't support inline.
CHECK_NE(mode, device::mojom::XRSessionMode::kInline);
// If the feature is AR-only, then it's only supported if the mode is AR.
if (IsArOnlyFeature(feature)) {
return mode == device::mojom::XRSessionMode::kImmersiveAr;
}
// If the feature isn't AR-only, then it's supported.
return true;
}
} // namespace device

@ -7,6 +7,7 @@
#include "base/logging.h"
#include "device/vr/public/mojom/pose.h"
#include "device/vr/public/mojom/xr_session.mojom.h"
#include "third_party/openxr/src/include/openxr/openxr.h"
#include "ui/gfx/geometry/transform.h"
#include "ui/gfx/geometry/transform_util.h"
@ -60,6 +61,9 @@ device::Pose XrPoseToDevicePose(const XrPosef& pose);
XrPosef GfxTransformToXrPose(const gfx::Transform& transform);
bool IsPoseValid(XrSpaceLocationFlags locationFlags);
bool IsFeatureSupportedForMode(device::mojom::XRSessionFeature feature,
device::mojom::XRSessionMode mode);
} // namespace device
#endif // DEVICE_VR_OPENXR_OPENXR_UTIL_H_