Commit 875db739 authored by Kevin Qin's avatar Kevin Qin Committed by Commit Bot

Handle All OpenXR Events

There are 3 more OpenXR events that require actions:
1. XrEventDataInstanceLossPending: Destroy instance and exit
presentation

2. XrEventDataInteractionProfileChanged: change WebXR input profiles

3. XrEventDataReferenceSpaceChangePending: Update Local to Stage Space
transform


Fixed: 1020354
Change-Id: I03ac3ef5fe4fcd70d4f1943c389456ca72ef1a75
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1842615
Commit-Queue: Zheng Qin <zheqi@microsoft.com>
Reviewed-by: default avatarMike West <mkwst@chromium.org>
Reviewed-by: default avatarAlexander Cooper <alcooper@chromium.org>
Cr-Commit-Position: refs/heads/master@{#711620}
parent 2cc1c99e
......@@ -141,10 +141,18 @@ void MockXRDeviceHookBase::WaitGetControllerData(
std::move(callback).Run(DeviceToMojoControllerFrameData(data));
}
void MockXRDeviceHookBase::WaitGetSessionStateStopping(
device_test::mojom::XRTestHook::WaitGetSessionStateStoppingCallback
callback) {
std::move(callback).Run(false);
void MockXRDeviceHookBase::WaitGetEventData(
device_test::mojom::XRTestHook::WaitGetEventDataCallback callback) {
if (event_data_queue_.empty()) {
device_test::mojom::EventDataPtr ret = device_test::mojom::EventData::New();
ret->type = device_test::mojom::EventType::kNoEvent;
std::move(callback).Run(std::move(ret));
return;
}
device_test::mojom::EventDataPtr ret =
device_test::mojom::EventData::New(event_data_queue_.front());
std::move(callback).Run(std::move(ret));
event_data_queue_.pop();
}
unsigned int MockXRDeviceHookBase::ConnectController(
......@@ -205,3 +213,7 @@ device::ControllerFrameData MockXRDeviceHookBase::CreateValidController(
ret.pose_data.device_to_origin[15] = 1;
return ret;
}
void MockXRDeviceHookBase::PopulateEvent(device_test::mojom::EventData data) {
event_data_queue_.push(data);
}
......@@ -5,6 +5,8 @@
#ifndef CHROME_BROWSER_VR_TEST_MOCK_XR_DEVICE_HOOK_BASE_H_
#define CHROME_BROWSER_VR_TEST_MOCK_XR_DEVICE_HOOK_BASE_H_
#include <queue>
#include "base/containers/flat_map.h"
#include "device/vr/public/mojom/browser_test_interfaces.mojom.h"
#include "device/vr/test/test_hook.h"
......@@ -41,9 +43,8 @@ class MockXRDeviceHookBase : public device_test::mojom::XRTestHook {
unsigned int index,
device_test::mojom::XRTestHook::WaitGetControllerDataCallback callback)
override;
void WaitGetSessionStateStopping(
device_test::mojom::XRTestHook::WaitGetSessionStateStoppingCallback
callback) override;
void WaitGetEventData(device_test::mojom::XRTestHook::WaitGetEventDataCallback
callback) override;
// MockXRDeviceHookBase
void TerminateDeviceServiceProcessForTesting();
......@@ -54,6 +55,7 @@ class MockXRDeviceHookBase : public device_test::mojom::XRTestHook {
void DisconnectController(unsigned int index);
device::ControllerFrameData CreateValidController(
device::ControllerRole role);
void PopulateEvent(device_test::mojom::EventData data);
void StopHooking();
protected:
......@@ -61,6 +63,7 @@ class MockXRDeviceHookBase : public device_test::mojom::XRTestHook {
tracked_classes_[device::kMaxTrackedDevices];
base::flat_map<unsigned int, device::ControllerFrameData>
controller_data_map_;
std::queue<device_test::mojom::EventData> event_data_queue_;
private:
mojo::Receiver<device_test::mojom::XRTestHook> receiver_{this};
......
......@@ -15,22 +15,6 @@
namespace vr {
class TransitionXRMock : public MockXRDeviceHookBase {
public:
void WaitGetSessionStateStopping(
device_test::mojom::XRTestHook::WaitGetSessionStateStoppingCallback
callback) final;
bool session_state_stopping_ = false;
};
void TransitionXRMock::WaitGetSessionStateStopping(
device_test::mojom::XRTestHook::WaitGetSessionStateStoppingCallback
callback) {
std::move(callback).Run(session_state_stopping_);
session_state_stopping_ = false;
}
// Tests that WebXR is not exposed if the flag is not on and the page does
// not have an origin trial token.
void TestApiDisabledWithoutFlagSetImpl(WebXrVrBrowserTestBase* t,
......@@ -124,24 +108,35 @@ WEBXR_VR_ALL_RUNTIMES_BROWSER_TEST_F(TestNonImmersiveStopsDuringImmersive) {
}
#if BUILDFLAG(ENABLE_OPENXR)
IN_PROC_BROWSER_TEST_F(WebXrVrOpenXrBrowserTest, TestSessionEnded) {
TransitionXRMock transition_mock;
// Load the test page, and enter presentation.
this->LoadUrlAndAwaitInitialization(
this->GetFileUrlForHtmlTestFile("test_webxr_presentation_ended"));
this->EnterSessionWithUserGestureOrFail();
// Tests that WebXR session ends when certain events are received.
void TestWebXRSessionEndWhenEventTriggered(
WebXrVrBrowserTestBase* t,
device_test::mojom::EventType event_type) {
MockXRDeviceHookBase transition_mock;
t->LoadUrlAndAwaitInitialization(
t->GetFileUrlForHtmlTestFile("test_webxr_presentation_ended"));
t->EnterSessionWithUserGestureOrFail();
// Wait for JavaScript to submit at least one frame.
ASSERT_TRUE(this->PollJavaScriptBoolean("hasPresentedFrame",
this->kPollTimeoutMedium))
ASSERT_TRUE(
t->PollJavaScriptBoolean("hasPresentedFrame", t->kPollTimeoutMedium))
<< "No frame submitted";
// Trigger the OpenXr Runtime to send the stop event and wait until we see the
// session get terminated.
transition_mock.session_state_stopping_ = true;
device_test::mojom::EventData data = {};
data.type = event_type;
transition_mock.PopulateEvent(data);
// Tell JavaScript that it is done with the test.
this->WaitOnJavaScriptStep();
this->EndTest();
t->WaitOnJavaScriptStep();
t->EndTest();
}
IN_PROC_BROWSER_TEST_F(WebXrVrOpenXrBrowserTest, TestSessionEnded) {
TestWebXRSessionEndWhenEventTriggered(
this, device_test::mojom::EventType::kSessionLost);
}
IN_PROC_BROWSER_TEST_F(WebXrVrOpenXrBrowserTest, TestInsanceLost) {
TestWebXRSessionEndWhenEventTriggered(
this, device_test::mojom::EventType::kInstanceLost);
}
#endif // BUILDFLAG(ENABLE_OPENXR)
......
......@@ -166,13 +166,16 @@ ControllerFrameData XRTestHookWrapper::WaitGetControllerData(
return {};
}
bool XRTestHookWrapper::WaitGetSessionStateStopping() {
device_test::mojom::EventData XRTestHookWrapper::WaitGetEventData() {
device_test::mojom::EventData ret = {};
if (hook_) {
bool stopping = false;
hook_->WaitGetSessionStateStopping(&stopping);
return stopping;
device_test::mojom::EventDataPtr data;
hook_->WaitGetEventData(&data);
if (data) {
ret = *data;
}
}
return false;
return ret;
}
void XRTestHookWrapper::AttachCurrentThread() {
......
......@@ -33,7 +33,7 @@ class XRTestHookWrapper : public VRTestHook {
unsigned int index) override;
TrackedDeviceClass WaitGetTrackedDeviceClass(unsigned int index) override;
ControllerFrameData WaitGetControllerData(unsigned int index) override;
bool WaitGetSessionStateStopping() override;
device_test::mojom::EventData WaitGetEventData() override;
void AttachCurrentThread() override;
void DetachCurrentThread() override;
......
......@@ -49,13 +49,13 @@ OpenXrApiWrapper::~OpenXrApiWrapper() {
}
void OpenXrApiWrapper::Reset() {
session_ended_ = false;
local_space_ = XR_NULL_HANDLE;
stage_space_ = XR_NULL_HANDLE;
view_space_ = XR_NULL_HANDLE;
color_swapchain_ = XR_NULL_HANDLE;
session_ = XR_NULL_HANDLE;
blend_mode_ = XR_ENVIRONMENT_BLEND_MODE_MAX_ENUM;
stage_bounds_ = {};
system_ = kInvalidSystem;
instance_ = XR_NULL_HANDLE;
......@@ -69,7 +69,7 @@ void OpenXrApiWrapper::Reset() {
bool OpenXrApiWrapper::Initialize() {
Reset();
session_ended_ = false;
if (XR_FAILED(CreateInstance(&instance_))) {
return false;
}
......@@ -114,6 +114,7 @@ void OpenXrApiWrapper::Uninitialize() {
test_hook_->DetachCurrentThread();
Reset();
session_ended_ = true;
}
bool OpenXrApiWrapper::HasInstance() const {
......@@ -595,6 +596,29 @@ XrResult OpenXrApiWrapper::ProcessEvents() {
default:
break;
}
} else if (event_data.type == XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING) {
DCHECK(session_ != XR_NULL_HANDLE);
Uninitialize();
} else if (event_data.type ==
XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING) {
XrEventDataReferenceSpaceChangePending* reference_space_change_pending =
reinterpret_cast<XrEventDataReferenceSpaceChangePending*>(
&event_data);
DCHECK(reference_space_change_pending->session == session_);
// TODO(crbug.com/1015049)
// Currently WMR only throw reference space change event for stage.
// Other runtimes may decide to do it differently.
if (reference_space_change_pending->referenceSpaceType ==
XR_REFERENCE_SPACE_TYPE_STAGE) {
UpdateStageBounds();
}
} else if (event_data.type ==
XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED) {
XrEventDataInteractionProfileChanged* interaction_profile_changed =
reinterpret_cast<XrEventDataInteractionProfileChanged*>(&event_data);
DCHECK(interaction_profile_changed->session == session_);
interaction_profile_changed_callback_.Run(&xr_result);
RETURN_IF_XR_FAILED(xr_result);
}
event_data.type = XR_TYPE_EVENT_DATA_BUFFER;
xr_result = xrPollEvent(instance_, &event_data);
......@@ -698,6 +722,13 @@ bool OpenXrApiWrapper::GetStageParameters(XrExtent2Df* stage_bounds,
return true;
}
void OpenXrApiWrapper::RegisterInteractionProfileChangeCallback(
const base::RepeatingCallback<void(XrResult*)>&
interaction_profile_callback) {
interaction_profile_changed_callback_ =
std::move(interaction_profile_callback);
}
VRTestHook* OpenXrApiWrapper::test_hook_ = nullptr;
ServiceTestHook* OpenXrApiWrapper::service_test_hook_ = nullptr;
void OpenXrApiWrapper::SetTestHook(VRTestHook* hook) {
......
......@@ -11,6 +11,7 @@
#include <memory>
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
#include "base/optional.h"
#include "device/vr/vr_export.h"
......@@ -59,6 +60,9 @@ class OpenXrApiWrapper {
std::string GetRuntimeName() const;
bool GetStageParameters(XrExtent2Df* stage_bounds,
gfx::Transform* local_from_stage);
void RegisterInteractionProfileChangeCallback(
const base::RepeatingCallback<void(XrResult*)>&
interaction_profile_callback);
static void DEVICE_VR_EXPORT SetTestHook(VRTestHook* hook);
......@@ -96,6 +100,9 @@ class OpenXrApiWrapper {
bool session_ended_;
base::RepeatingCallback<void(XrResult*)>
interaction_profile_changed_callback_;
// Testing objects
static VRTestHook* test_hook_;
static ServiceTestHook* service_test_hook_;
......
This diff is collapsed.
......@@ -8,6 +8,7 @@
#include <stdint.h>
#include <map>
#include <unordered_map>
#include <vector>
#include "base/optional.h"
#include "device/vr/public/mojom/vr_service.mojom.h"
......@@ -53,7 +54,7 @@ class OpenXrController {
uint32_t GetId() const;
device::mojom::XRHandedness GetHandness() const;
device::mojom::XRInputSourceDescriptionPtr GetDescription(
mojom::XRInputSourceDescriptionPtr GetDescription(
XrTime predicted_display_time);
base::Optional<GamepadButton> GetButton(OpenXrButtonType type) const;
......@@ -63,6 +64,8 @@ class OpenXrController {
XrTime predicted_display_time,
XrSpace local_space) const;
XrResult UpdateInteractionProfile();
private:
// ActionButton struct is used to store all XrAction that is related to the
// button. For example, we may need to query the analog value for button press
......@@ -78,14 +81,12 @@ class OpenXrController {
};
XrResult InitializeMicrosoftMotionControllerActions(
XrInstance instance,
const std::string& type_string,
std::map<XrPath, std::vector<XrActionSuggestedBinding>>* bindings);
XrResult InitializeMicrosoftMotionControllerSpaces();
XrResult CreateAction(
XrInstance instance,
XrActionType type,
const char* interaction_profile_name,
const std::string& binding_string,
......@@ -103,6 +104,8 @@ class OpenXrController {
XrSpace target,
XrSpace origin) const;
std::vector<std::string> GetProfiles() const;
template <typename T>
XrResult QueryState(XrAction action, T* action_state) const {
// this function should never be called because each valid XrActionState
......@@ -154,6 +157,7 @@ class OpenXrController {
device::mojom::XRInputSourceDescriptionPtr description_;
OpenXrHandednessType type_;
XrInstance instance_;
XrSession session_;
XrActionSet action_set_;
XrAction grip_pose_action_;
......@@ -161,6 +165,9 @@ class OpenXrController {
XrAction pointer_pose_action_;
XrSpace pointer_pose_space_;
std::string interaction_profile_;
std::string top_level_user_path_string_;
std::unordered_map<OpenXrButtonType, ActionButton> button_action_map_;
std::unordered_map<OpenXrAxisType, XrAction> axis_action_map_;
......
......@@ -120,8 +120,10 @@ std::vector<mojom::XRInputSourceStatePtr> OpenXRInputHelper::GetInputState(
// To ensure that we don't have any collisions with other ids, increment
// all of the ids by one.
state->source_id = i + 1;
state->description = controller->GetDescription(predicted_display_time);
if (!state->description) {
continue;
}
state->mojo_from_input = controller->GetMojoFromGripTransform(
predicted_display_time, local_space_);
......@@ -138,6 +140,19 @@ std::vector<mojom::XRInputSourceStatePtr> OpenXRInputHelper::GetInputState(
return input_states;
}
void OpenXRInputHelper::OnInteractionProfileChanged(XrResult* xr_result) {
for (OpenXrControllerState& controller_state : controller_states_) {
*xr_result = controller_state.controller.UpdateInteractionProfile();
if (XR_FAILED(*xr_result)) {
return;
}
}
}
base::WeakPtr<OpenXRInputHelper> OpenXRInputHelper::GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
base::Optional<Gamepad> OpenXRInputHelper::GetWebXRGamepad(
const OpenXrController& controller) const {
XRStandardGamepadBuilder builder(controller.GetHandness());
......
......@@ -30,6 +30,10 @@ class OpenXRInputHelper {
std::vector<mojom::XRInputSourceStatePtr> GetInputState(
XrTime predicted_display_time);
void OnInteractionProfileChanged(XrResult* xr_result);
base::WeakPtr<OpenXRInputHelper> GetWeakPtr();
private:
base::Optional<Gamepad> GetWebXRGamepad(
const OpenXrController& controller) const;
......@@ -47,6 +51,9 @@ class OpenXRInputHelper {
static_cast<size_t>(OpenXrHandednessType::kCount)>
controller_states_;
// This must be the last member
base::WeakPtrFactory<OpenXRInputHelper> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(OpenXRInputHelper);
};
......
......@@ -104,6 +104,10 @@ bool OpenXrRenderLoop::StartRuntime() {
openxr_ = std::move(openxr);
texture_helper_.SetDefaultSize(openxr_->GetViewSize());
openxr_->RegisterInteractionProfileChangeCallback(
base::BindRepeating(&OpenXRInputHelper::OnInteractionProfileChanged,
input_helper_->GetWeakPtr()));
DCHECK(openxr_);
DCHECK(input_helper_);
InitializeDisplayInfo();
......
......@@ -8,8 +8,10 @@
#include <stdint.h>
#include <memory>
#include "base/callback.h"
#include "base/macros.h"
#include "device/vr/windows/compositor_base.h"
#include "third_party/openxr/src/include/openxr/openxr.h"
struct XrView;
......
......@@ -558,6 +558,24 @@ XrResult xrGetInstanceProperties(XrInstance instance,
return XR_SUCCESS;
}
XrResult xrGetCurrentInteractionProfile(
XrSession session,
XrPath topLevelUserPath,
XrInteractionProfileState* interactionProfile) {
DVLOG(1) << __FUNCTION__;
XrResult xr_result;
RETURN_IF_XR_FAILED(g_test_helper.ValidateSession(session));
RETURN_IF(interactionProfile->type != XR_TYPE_INTERACTION_PROFILE_STATE,
XR_ERROR_VALIDATION_FAILURE,
"xrGetCurrentInteractionProfile type is not "
"XR_TYPE_INTERACTION_PROFILE_STATE");
RETURN_IF_XR_FAILED(g_test_helper.ValidatePath(topLevelUserPath));
interactionProfile->interactionProfile =
g_test_helper.GetCurrentInteractionProfile();
return XR_SUCCESS;
}
XrResult xrGetReferenceSpaceBoundsRect(XrSession session,
XrReferenceSpaceType referenceSpaceType,
XrExtent2Df* bounds) {
......@@ -655,17 +673,8 @@ XrResult xrPollEvent(XrInstance instance, XrEventDataBuffer* event_data) {
RETURN_IF_FALSE(event_data->type == XR_TYPE_EVENT_DATA_BUFFER,
XR_ERROR_VALIDATION_FAILURE,
"xrPollEvent event_data type invalid");
RETURN_IF_FALSE(g_test_helper.UpdateSessionStateEventQueue(),
XR_ERROR_VALIDATION_FAILURE,
"Update SessionStateEventQueue failed.");
if (g_test_helper.HasPendingSessionStateEvent()) {
XrEventDataSessionStateChanged* event_data_ptr =
reinterpret_cast<XrEventDataSessionStateChanged*>(event_data);
*event_data_ptr = g_test_helper.GetNextSessionStateEvent();
return XR_SUCCESS;
}
return XR_EVENT_UNAVAILABLE;
return g_test_helper.PollEvent(event_data);
}
XrResult xrReleaseSwapchainImage(
......@@ -725,6 +734,34 @@ XrResult xrStringToPath(XrInstance instance,
return XR_SUCCESS;
}
XrResult xrPathToString(XrInstance instance,
XrPath path,
uint32_t bufferCapacityInput,
uint32_t* bufferCountOutput,
char* buffer) {
DVLOG(1) << __FUNCTION__;
XrResult xr_result;
RETURN_IF_XR_FAILED(g_test_helper.ValidateInstance(instance));
RETURN_IF_XR_FAILED(g_test_helper.ValidatePath(path));
std::string path_string = g_test_helper.PathToString(path);
if (bufferCapacityInput == 0) {
// OpenXR spec counts terminating '\0'
*bufferCountOutput = path_string.size() + 1;
return XR_SUCCESS;
}
RETURN_IF(
*bufferCountOutput <= path_string.size(), XR_ERROR_SIZE_INSUFFICIENT,
"xrPathToString inputsize is not large enough to hold the output string");
errno_t error = strcpy_s(buffer, *bufferCountOutput, path_string.data());
DCHECK(error == 0);
return XR_SUCCESS;
}
XrResult xrSyncActions(XrSession session, const XrActionsSyncInfo* sync_info) {
DVLOG(2) << __FUNCTION__;
XrResult xr_result;
......
......@@ -78,6 +78,9 @@ XrResult XRAPI_PTR GetInstanceProcAddress(XrInstance instance,
*function = reinterpret_cast<PFN_xrVoidFunction>(xrGetActionStatePose);
} else if (strcmp(name, "xrGetInstanceProperties") == 0) {
*function = reinterpret_cast<PFN_xrVoidFunction>(xrGetInstanceProperties);
} else if (strcmp(name, "xrGetCurrentInteractionProfile") == 0) {
*function =
reinterpret_cast<PFN_xrVoidFunction>(xrGetCurrentInteractionProfile);
} else if (strcmp(name, "xrGetReferenceSpaceBoundsRect") == 0) {
*function =
reinterpret_cast<PFN_xrVoidFunction>(xrGetReferenceSpaceBoundsRect);
......@@ -98,6 +101,8 @@ XrResult XRAPI_PTR GetInstanceProcAddress(XrInstance instance,
xrSuggestInteractionProfileBindings);
} else if (strcmp(name, "xrStringToPath") == 0) {
*function = reinterpret_cast<PFN_xrVoidFunction>(xrStringToPath);
} else if (strcmp(name, "xrPathToString") == 0) {
*function = reinterpret_cast<PFN_xrVoidFunction>(xrPathToString);
} else if (strcmp(name, "xrSyncActions") == 0) {
*function = reinterpret_cast<PFN_xrVoidFunction>(xrSyncActions);
} else if (strcmp(name, "xrWaitFrame") == 0) {
......
......@@ -311,6 +311,10 @@ XrPath OpenXrTestHelper::GetPath(const char* path_string) {
return paths_.size() - 1;
}
XrPath OpenXrTestHelper::GetCurrentInteractionProfile() {
return GetPath("/interaction_profiles/microsoft/motion_controller");
}
XrResult OpenXrTestHelper::BeginSession() {
RETURN_IF(session_state_ != XR_SESSION_STATE_READY,
XR_ERROR_VALIDATION_FAILURE,
......@@ -468,19 +472,27 @@ XrResult OpenXrTestHelper::UpdateAction(XrAction action) {
void OpenXrTestHelper::SetSessionState(XrSessionState state) {
session_state_ = state;
XrEventDataSessionStateChanged event = {
XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED};
event.session = session_;
event.state = session_state_;
event.time = next_predicted_display_time_;
session_state_event_queue_.push(event);
XrEventDataBuffer event_data;
XrEventDataSessionStateChanged* event_data_ptr =
reinterpret_cast<XrEventDataSessionStateChanged*>(&event_data);
event_data_ptr->type = XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED;
event_data_ptr->session = session_;
event_data_ptr->state = session_state_;
event_data_ptr->time = next_predicted_display_time_;
event_queue_.push(event_data);
}
XrEventDataSessionStateChanged OpenXrTestHelper::GetNextSessionStateEvent() {
DCHECK(HasPendingSessionStateEvent());
XrEventDataSessionStateChanged front = session_state_event_queue_.front();
session_state_event_queue_.pop();
return front;
XrResult OpenXrTestHelper::PollEvent(XrEventDataBuffer* event_data) {
UpdateEventQueue();
if (!event_queue_.empty()) {
*event_data = event_queue_.front();
event_queue_.pop();
return XR_SUCCESS;
}
return XR_EVENT_UNAVAILABLE;
}
const std::vector<Microsoft::WRL::ComPtr<ID3D11Texture2D>>&
......@@ -498,20 +510,24 @@ XrTime OpenXrTestHelper::NextPredictedDisplayTime() {
return ++next_predicted_display_time_;
}
bool OpenXrTestHelper::UpdateSessionStateEventQueue() {
void OpenXrTestHelper::UpdateEventQueue() {
base::AutoLock auto_lock(lock_);
if (test_hook_) {
if (test_hook_->WaitGetSessionStateStopping()) {
SetSessionState(XR_SESSION_STATE_STOPPING);
}
return true;
device_test::mojom::EventData data = {};
do {
data = test_hook_->WaitGetEventData();
if (data.type == device_test::mojom::EventType::kSessionLost) {
SetSessionState(XR_SESSION_STATE_STOPPING);
} else if (data.type == device_test::mojom::EventType::kInstanceLost) {
XrEventDataBuffer event_data = {
XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING};
event_queue_.push(event_data);
} else if (data.type != device_test::mojom::EventType::kNoEvent) {
NOTREACHED() << "Event changed tests other than session lost and "
"instance lost is not implemented";
}
} while (data.type != device_test::mojom::EventType::kNoEvent);
}
return false;
}
bool OpenXrTestHelper::HasPendingSessionStateEvent() {
return !session_state_event_queue_.empty();
}
base::Optional<gfx::Transform> OpenXrTestHelper::GetPose() {
......
......@@ -56,6 +56,7 @@ class OpenXrTestHelper : public device::ServiceTestHook {
XrActionSet CreateActionSet(const XrActionSetCreateInfo& createInfo);
XrSpace CreateActionSpace(XrAction);
XrPath GetPath(const char* path_string);
XrPath GetCurrentInteractionProfile();
XrResult GetSession(XrSession* session);
XrResult BeginSession();
......@@ -75,9 +76,8 @@ class OpenXrTestHelper : public device::ServiceTestHook {
uint32_t NextSwapchainImageIndex();
XrTime NextPredictedDisplayTime();
bool UpdateSessionStateEventQueue();
bool HasPendingSessionStateEvent();
XrEventDataSessionStateChanged GetNextSessionStateEvent();
void UpdateEventQueue();
XrResult PollEvent(XrEventDataBuffer* event_data);
// Methods that validate the parameter with the current state of the runtime.
XrResult ValidateAction(XrAction action) const;
......@@ -169,9 +169,7 @@ class OpenXrTestHelper : public device::ServiceTestHook {
std::array<device::ControllerFrameData, device::kMaxTrackedDevices> data_arr_;
// session_state_event_queue_ is used to store XrEventDataSessionStateChanged
// event whenever session state changes.
std::queue<XrEventDataSessionStateChanged> session_state_event_queue_;
std::queue<XrEventDataBuffer> event_queue_;
device::VRTestHook* test_hook_ GUARDED_BY(lock_) = nullptr;
base::Lock lock_;
......
......@@ -80,6 +80,18 @@ struct ControllerFrameData {
bool is_valid;
};
// Event type is used by test to simulate runtime events.
enum EventType {
kSessionLost,
kInstanceLost,
kNoEvent
};
// EventData is used by test to pass all event related data.
struct EventData {
EventType type = kNoEvent;
};
// Tests may implement this, and register it to control behavior of devices for
// tests. The test interface lives in the browser process, and may be consumed
// by the device utility process.
......@@ -118,10 +130,8 @@ interface XRTestHook {
// given index, e.g. its current position and pressed buttons.
[Sync] WaitGetControllerData(uint32 index) => (ControllerFrameData data);
// Called by the OpenXR test. Test can inform runtime when it should stop
// session by calling this function and test if such events are handled
// correctly.
[Sync] WaitGetSessionStateStopping() => (bool stopping);
// Called by the OpenXR test to simulate runtime events.
[Sync] WaitGetEventData() => (EventData data);
};
// Interface exposed by IsolatedXRService to allow browser tests to hook VR APIs
......
......@@ -6,6 +6,7 @@
#define DEVICE_VR_TEST_TEST_HOOK_H_
#include "base/logging.h"
#include "device/vr/public/mojom/browser_test_interfaces.mojom.h"
#include "ui/gfx/transform.h"
#include <cstdint>
......@@ -145,7 +146,7 @@ class VRTestHook {
unsigned int index) = 0;
virtual TrackedDeviceClass WaitGetTrackedDeviceClass(unsigned int index) = 0;
virtual ControllerFrameData WaitGetControllerData(unsigned int index) = 0;
virtual bool WaitGetSessionStateStopping() = 0;
virtual device_test::mojom::EventData WaitGetEventData() = 0;
virtual void AttachCurrentThread() = 0;
virtual void DetachCurrentThread() = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment