| // Copyright 2018 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/webxr/xr_test_hook_wrapper.h" |
| |
| #include "base/task/single_thread_task_runner.h" |
| #include "mojo/public/cpp/bindings/sync_call_restrictions.h" |
| |
| namespace webxr { |
| |
| // TODO(crbug.com/41418750): Remove these as conversion functions as part |
| // of the switch to only mojom types. |
| device::ControllerRole MojoToDeviceControllerRole( |
| device_test::mojom::ControllerRole role) { |
| switch (role) { |
| case device_test::mojom::ControllerRole::kControllerRoleInvalid: |
| return device::kControllerRoleInvalid; |
| case device_test::mojom::ControllerRole::kControllerRoleLeft: |
| return device::kControllerRoleLeft; |
| case device_test::mojom::ControllerRole::kControllerRoleRight: |
| return device::kControllerRoleRight; |
| case device_test::mojom::ControllerRole::kControllerRoleVoice: |
| return device::kControllerRoleVoice; |
| } |
| return device::kControllerRoleInvalid; |
| } |
| |
| device::PoseFrameData MojoToDevicePoseFrameData( |
| device_test::mojom::PoseFrameDataPtr& pose) { |
| device::PoseFrameData ret = {}; |
| ret.is_valid = !!pose->device_to_origin; |
| if (ret.is_valid) { |
| pose->device_to_origin->GetColMajorF(ret.device_to_origin.data()); |
| } |
| |
| return ret; |
| } |
| |
| device_test::mojom::Eye XrEyeToMojoEye(device::XrEye eye) { |
| switch (eye) { |
| case device::XrEye::kLeft: |
| return device_test::mojom::Eye::LEFT; |
| case device::XrEye::kRight: |
| return device_test::mojom::Eye::RIGHT; |
| case device::XrEye::kNone: |
| return device_test::mojom::Eye::NONE; |
| } |
| } |
| |
| XRTestHookWrapper::XRTestHookWrapper( |
| mojo::PendingRemote<device_test::mojom::XRTestHook> pending_hook) |
| : pending_hook_(std::move(pending_hook)) {} |
| |
| void XRTestHookWrapper::OnFrameSubmitted( |
| const std::vector<device::ViewData>& views) { |
| if (hook_) { |
| std::vector<device_test::mojom::ViewDataPtr> submitted_views; |
| for (const device::ViewData& view : views) { |
| device_test::mojom::ViewDataPtr view_data = |
| device_test::mojom::ViewData::New(); |
| view_data->color = device_test::mojom::Color::New( |
| view.color.r, view.color.g, view.color.b, view.color.a); |
| view_data->viewport = view.viewport; |
| view_data->eye = XrEyeToMojoEye(view.eye); |
| submitted_views.push_back(std::move(view_data)); |
| } |
| mojo::ScopedAllowSyncCallForTesting scoped_allow_sync; |
| hook_->OnFrameSubmitted(std::move(submitted_views)); |
| } |
| } |
| |
| device::DeviceConfig XRTestHookWrapper::WaitGetDeviceConfig() { |
| if (hook_) { |
| mojo::ScopedAllowSyncCallForTesting scoped_allow_sync; |
| device_test::mojom::DeviceConfigPtr config; |
| hook_->WaitGetDeviceConfig(&config); |
| if (config) { |
| device::DeviceConfig ret = {}; |
| ret.interpupillary_distance = config->interpupillary_distance; |
| ret.viewport_left[0] = config->projection_left->left; |
| ret.viewport_left[1] = config->projection_left->right; |
| ret.viewport_left[2] = config->projection_left->top; |
| ret.viewport_left[3] = config->projection_left->left; |
| |
| ret.viewport_right[0] = config->projection_right->left; |
| ret.viewport_right[1] = config->projection_right->right; |
| ret.viewport_right[2] = config->projection_right->top; |
| ret.viewport_right[3] = config->projection_right->left; |
| return ret; |
| } |
| } |
| |
| return {}; |
| } |
| |
| device::PoseFrameData XRTestHookWrapper::WaitGetPresentingPose() { |
| if (hook_) { |
| mojo::ScopedAllowSyncCallForTesting scoped_allow_sync; |
| device_test::mojom::PoseFrameDataPtr pose; |
| hook_->WaitGetPresentingPose(&pose); |
| if (pose) { |
| return MojoToDevicePoseFrameData(pose); |
| } |
| } |
| |
| return {}; |
| } |
| |
| device::PoseFrameData XRTestHookWrapper::WaitGetMagicWindowPose() { |
| if (hook_) { |
| mojo::ScopedAllowSyncCallForTesting scoped_allow_sync; |
| device_test::mojom::PoseFrameDataPtr pose; |
| hook_->WaitGetMagicWindowPose(&pose); |
| if (pose) { |
| return MojoToDevicePoseFrameData(pose); |
| } |
| } |
| |
| return {}; |
| } |
| |
| device::ControllerRole |
| XRTestHookWrapper::WaitGetControllerRoleForTrackedDeviceIndex( |
| unsigned int index) { |
| if (hook_) { |
| mojo::ScopedAllowSyncCallForTesting scoped_allow_sync; |
| device_test::mojom::ControllerRole role; |
| hook_->WaitGetControllerRoleForTrackedDeviceIndex(index, &role); |
| return MojoToDeviceControllerRole(role); |
| } |
| |
| return device::kControllerRoleInvalid; |
| } |
| |
| device::TrackedDeviceClass XRTestHookWrapper::WaitGetTrackedDeviceClass( |
| unsigned int index) { |
| if (hook_) { |
| mojo::ScopedAllowSyncCallForTesting scoped_allow_sync; |
| device_test::mojom::TrackedDeviceClass device_class; |
| hook_->WaitGetTrackedDeviceClass(index, &device_class); |
| switch (device_class) { |
| case device_test::mojom::TrackedDeviceClass::kTrackedDeviceInvalid: |
| return device::kTrackedDeviceInvalid; |
| case device_test::mojom::TrackedDeviceClass::kTrackedDeviceHmd: |
| return device::kTrackedDeviceHmd; |
| case device_test::mojom::TrackedDeviceClass::kTrackedDeviceController: |
| return device::kTrackedDeviceController; |
| case device_test::mojom::TrackedDeviceClass::kTrackedDeviceGenericTracker: |
| return device::kTrackedDeviceGenericTracker; |
| case device_test::mojom::TrackedDeviceClass:: |
| kTrackedDeviceTrackingReference: |
| return device::kTrackedDeviceTrackingReference; |
| case device_test::mojom::TrackedDeviceClass:: |
| kTrackedDeviceDisplayRedirect: |
| return device::kTrackedDeviceDisplayRedirect; |
| } |
| } |
| |
| return device::kTrackedDeviceInvalid; |
| } |
| |
| device::ControllerFrameData XRTestHookWrapper::WaitGetControllerData( |
| unsigned int index) { |
| if (hook_) { |
| mojo::ScopedAllowSyncCallForTesting scoped_allow_sync; |
| device_test::mojom::ControllerFrameDataPtr data; |
| hook_->WaitGetControllerData(index, &data); |
| if (data) { |
| device::ControllerFrameData ret = {}; |
| ret.packet_number = data->packet_number; |
| ret.buttons_pressed = data->buttons_pressed; |
| ret.buttons_touched = data->buttons_touched; |
| ret.supported_buttons = data->supported_buttons; |
| ret.pose_data = MojoToDevicePoseFrameData(data->pose_data); |
| ret.role = MojoToDeviceControllerRole(data->role); |
| ret.is_valid = data->is_valid; |
| for (unsigned int i = 0; i < device::kMaxNumAxes; ++i) { |
| ret.axis_data[i].x = data->axis_data[i]->x; |
| ret.axis_data[i].y = data->axis_data[i]->y; |
| ret.axis_data[i].axis_type = data->axis_data[i]->axis_type; |
| } |
| if (data->hand_data) { |
| ret.has_hand_data = true; |
| auto& joint_data = ret.hand_data; |
| CHECK_GE(std::size(joint_data), |
| data->hand_data->hand_joint_data.size()); |
| |
| for (const auto& joint_entry : data->hand_data->hand_joint_data) { |
| uint32_t joint_index = static_cast<uint32_t>(joint_entry->joint); |
| |
| joint_data[joint_index] = {joint_entry->joint, |
| joint_entry->mojo_from_joint, |
| joint_entry->radius}; |
| } |
| } |
| return ret; |
| } |
| } |
| |
| return {}; |
| } |
| |
| device_test::mojom::EventData XRTestHookWrapper::WaitGetEventData() { |
| device_test::mojom::EventData ret = {}; |
| if (hook_) { |
| mojo::ScopedAllowSyncCallForTesting scoped_allow_sync; |
| device_test::mojom::EventDataPtr data; |
| hook_->WaitGetEventData(&data); |
| if (data) { |
| ret = *data; |
| } |
| } |
| return ret; |
| } |
| |
| bool XRTestHookWrapper::WaitGetCanCreateSession() { |
| if (hook_) { |
| mojo::ScopedAllowSyncCallForTesting scoped_allow_sync; |
| bool can_create_session; |
| hook_->WaitGetCanCreateSession(&can_create_session); |
| return can_create_session; |
| } |
| |
| // In the absence of a test hook telling us that we can't create a session; |
| // assume that we can, there's often enough default behavior to do so, and |
| // some tests expect to be able to get a session without creating a test hook. |
| return true; |
| } |
| |
| void XRTestHookWrapper::AttachCurrentThread() { |
| if (pending_hook_) { |
| hook_.Bind(std::move(pending_hook_)); |
| } |
| |
| current_task_runner_ = base::SingleThreadTaskRunner::GetCurrentDefault(); |
| } |
| |
| void XRTestHookWrapper::DetachCurrentThread() { |
| if (hook_) { |
| pending_hook_ = hook_.Unbind(); |
| } |
| |
| current_task_runner_ = nullptr; |
| } |
| |
| scoped_refptr<base::SingleThreadTaskRunner> |
| XRTestHookWrapper::GetBoundTaskRunner() { |
| return current_task_runner_; |
| } |
| |
| XRTestHookWrapper::~XRTestHookWrapper() = default; |
| |
| } // namespace webxr |