#include "device/vr/openxr/windows/openxr_platform_helper_windows.h"
#include <memory>
#include <vector>
#include "base/containers/contains.h"
#include "base/memory/weak_ptr.h"
#include "base/win/scoped_handle.h"
#include "base/win/windows_types.h"
#include "device/vr/openxr/openxr_api_wrapper.h"
#include "device/vr/openxr/windows/openxr_graphics_binding_d3d11.h"
#include "device/vr/openxr/windows/openxr_instance_wrapper.h"
#include "device/vr/public/mojom/isolated_xr_service.mojom.h"
#include "third_party/openxr/src/include/openxr/openxr.h"
namespace device {
namespace {
bool IsRunningInWin32AppContainer() {
base::win::ScopedHandle scopedProcessToken;
HANDLE processToken;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &processToken)) {
return false;
}
scopedProcessToken.Set(processToken);
BOOL isAppContainer;
DWORD dwSize = sizeof(BOOL);
if (!GetTokenInformation(scopedProcessToken.Get(), TokenIsAppContainer,
&isAppContainer, dwSize, &dwSize)) {
return false;
}
return isAppContainer;
}
}
void OpenXrPlatformHelper::GetRequiredExtensions(
std::vector<const char*>& extensions) {
if (IsRunningInWin32AppContainer()) {
extensions.push_back(XR_EXT_WIN32_APPCONTAINER_COMPATIBLE_EXTENSION_NAME);
}
}
std::vector<const char*> OpenXrPlatformHelper::GetOptionalExtensions() {
std::vector<const char*> extensions;
extensions.push_back(
XR_KHR_WIN32_CONVERT_PERFORMANCE_COUNTER_TIME_EXTENSION_NAME);
return extensions;
}
OpenXrPlatformHelperWindows::OpenXrPlatformHelperWindows() = default;
OpenXrPlatformHelperWindows::~OpenXrPlatformHelperWindows() = default;
std::unique_ptr<OpenXrGraphicsBinding>
OpenXrPlatformHelperWindows::GetGraphicsBinding() {
return std::make_unique<OpenXrGraphicsBindingD3D11>(
weak_ptr_factory_.GetWeakPtr());
}
void OpenXrPlatformHelperWindows::GetPlatformCreateInfo(
const device::OpenXrCreateInfo& create_info,
PlatformCreateInfoReadyCallback result_callback,
PlatormInitiatedShutdownCallback shutdown_callback) {
std::move(result_callback).Run(nullptr);
}
device::mojom::XRDeviceData OpenXrPlatformHelperWindows::GetXRDeviceData() {
device::mojom::XRDeviceData device_data;
device_data.is_ar_blend_mode_supported =
IsArBlendModeSupported(GetOrCreateXrInstance());
if (LUID luid; TryGetLuid(&luid)) {
device_data.luid = CHROME_LUID{luid.LowPart, luid.HighPart};
}
return device_data;
}
bool OpenXrPlatformHelperWindows::TryGetLuid(LUID* luid, XrSystemId system) {
CHECK(luid);
XrInstance instance = GetOrCreateXrInstance();
if (instance == XR_NULL_HANDLE) {
return false;
}
if (system == XR_NULL_SYSTEM_ID &&
XR_FAILED(OpenXrApiWrapper::GetSystem(instance, &system))) {
return false;
}
if (get_graphics_requirements_fn_ == nullptr) {
if (XR_FAILED(xrGetInstanceProcAddr(
instance, "xrGetD3D11GraphicsRequirementsKHR",
(PFN_xrVoidFunction*)(&get_graphics_requirements_fn_))) ||
get_graphics_requirements_fn_ == nullptr) {
return false;
}
}
XrGraphicsRequirementsD3D11KHR graphics_requirements = {
XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR};
if (XR_FAILED(get_graphics_requirements_fn_(instance, system,
&graphics_requirements))) {
return false;
}
*luid = graphics_requirements.adapterLuid;
return luid->HighPart != 0 || luid->LowPart != 0;
}
bool OpenXrPlatformHelperWindows::IsHardwareAvailable() {
XrInstance instance = GetOrCreateXrInstance();
if (instance == XR_NULL_HANDLE) {
return false;
}
XrSystemId system;
return XR_SUCCEEDED(OpenXrApiWrapper::GetSystem(instance, &system));
}
bool OpenXrPlatformHelperWindows::IsApiAvailable() {
return GetOrCreateXrInstance() != XR_NULL_HANDLE;
}
bool OpenXrPlatformHelperWindows::Initialize() {
return true;
}
void OpenXrPlatformHelperWindows::PrepareForSessionShutdown(
base::OnceClosure shutdown_ready_callback) {
std::move(shutdown_ready_callback).Run();
}
XrResult OpenXrPlatformHelperWindows::CreateInstance(XrInstance* instance,
void* create_info) {
CHECK(instance);
auto* instance_wrapper = OpenXrInstanceWrapper::GetWrapper();
if (instance_wrapper->HasXrInstance()) {
*instance = instance_wrapper->GetXrInstance();
return XR_SUCCESS;
}
XrResult result = OpenXrPlatformHelper::CreateInstance(instance, create_info);
if (XR_SUCCEEDED(result)) {
instance_wrapper->SetXrInstance(*instance);
}
return result;
}
XrInstance OpenXrPlatformHelperWindows::GetOrCreateXrInstance() {
XrInstance instance = XR_NULL_HANDLE;
(void)CreateInstance(&instance, nullptr);
return instance;
}
XrResult OpenXrPlatformHelperWindows::DestroyInstance(XrInstance& instance) {
CHECK(instance != XR_NULL_HANDLE);
instance = XR_NULL_HANDLE;
xr_instance_ = XR_NULL_HANDLE;
return XR_SUCCESS;
}
}