chromium/device/vr/openxr/openxr_path_helper.cc

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "device/vr/openxr/openxr_path_helper.h"

#include "base/check.h"
#include "base/containers/contains.h"
#include "device/vr/openxr/openxr_interaction_profiles.h"
#include "device/vr/openxr/openxr_util.h"
#include "device/vr/public/mojom/openxr_interaction_profile_type.mojom.h"

namespace device {

using device::mojom::OpenXrInteractionProfileType;

namespace {
constexpr std::array<OpenXrInteractionProfileType, 3> kHandProfiles{
    OpenXrInteractionProfileType::kHandSelectGrasp,
    OpenXrInteractionProfileType::kExtHand,
    OpenXrInteractionProfileType::kMetaHandAim,
};
}  // namespace

OpenXRPathHelper::OpenXRPathHelper() = default;

OpenXRPathHelper::~OpenXRPathHelper() = default;

XrResult OpenXRPathHelper::Initialize(XrInstance instance, XrSystemId system) {
  DCHECK(!initialized_);

  // Get the system properties, which is needed to determine the name of the
  // hardware being used. This helps disambiguate certain sets of controllers.
  XrSystemProperties system_properties = {XR_TYPE_SYSTEM_PROPERTIES};
  RETURN_IF_XR_FAILED(
      xrGetSystemProperties(instance, system, &system_properties));
  system_name_ = std::string(system_properties.systemName);

  // Create path declarations
  for (const auto& profile : GetOpenXrControllerInteractionProfiles()) {
    RETURN_IF_XR_FAILED(
        xrStringToPath(instance, profile.path.c_str(),
                       &(declared_interaction_profile_paths_[profile.type])));
  }
  initialized_ = true;

  return XR_SUCCESS;
}

OpenXrInteractionProfileType OpenXRPathHelper::GetInputProfileType(
    XrPath interaction_profile) const {
  DCHECK(initialized_);
  for (auto it : declared_interaction_profile_paths_) {
    if (it.second == interaction_profile) {
      return it.first;
    }
  }
  return OpenXrInteractionProfileType::kInvalid;
}

std::vector<std::string> OpenXRPathHelper::GetInputProfiles(
    OpenXrInteractionProfileType interaction_profile,
    bool hand_joints_enabled) const {
  DCHECK(initialized_);

  bool can_use_hand_joint_profile =
      hand_joints_enabled && base::Contains(kHandProfiles, interaction_profile);

  const auto& input_profiles_map = GetOpenXrInputProfilesMap();
  if (input_profiles_map.contains(interaction_profile)) {
    const OpenXrSystemInputProfiles* active_system = nullptr;
    for (const auto& system : input_profiles_map.at(interaction_profile)) {
      if ((!can_use_hand_joint_profile && system.system_name.empty()) ||
          (can_use_hand_joint_profile &&
           system.system_name.compare(kOpenXrHandJointSystem) == 0)) {
        active_system = &system;
      } else if (system_name_.compare(system.system_name) == 0) {
        active_system = &system;
        break;
      }
    }

    // Each interaction profile should always at least have a null system_name
    // entry. Profiles that support hand joints should have both a null
    // system_name and a `kOpenXrHandJointSystem` system_name.
    DCHECK(active_system);
    return active_system->input_profiles;
  }

  return {};
}

XrPath OpenXRPathHelper::GetInteractionProfileXrPath(
    OpenXrInteractionProfileType type) const {
  if (type == OpenXrInteractionProfileType::kInvalid) {
    return XR_NULL_PATH;
  }
  return declared_interaction_profile_paths_.at(type);
}

}  // namespace device