Commit 7f94d7ae authored by Alex Cooper's avatar Alex Cooper Committed by Commit Bot

Revert "Update XRInputSource Gamepad to comply with SameObject requirement"

This reverts commit f9706cfd.

Reason for revert:963529

Original change's description:
> Update XRInputSource Gamepad to comply with SameObject requirement
>
> The WebXR spec requires that the Gamepad object on an XRInputSource be
> tagged as "SameObject."  The current implementation would allow for
> the Gamepad to be toggled between null and present on the same
> XRInputSource object as it currently is written.  This change exposes a
> method "NeedsReCreation" as well as static helper methods (and a deep-
> copy constructor) to allow for that re-creation to occur in a pattern
> which could be re-used by 958019 if the spec requires those changes.
> While this change adds an xr_browser_test to validate the blink code
> that destroys/re-creates the object, the work to add a WPT test for all
> of the same object properties is tracked by 960958.
>
> The exemption to audit_non_blink_usage was added because the xr module
> was currently utilizing device::Gamepad, but since it was previously
> wrapped in base::Optional, that usage was not flagged.
>
> Note that 955101 (currently tagged for 77) may relax/change this
> requirement, but this makes the code compliant with the spec for M76.
>
> Bug: 960978
> Change-Id: Ie36990f47e43c6df91af3fca06dd269a860a2a1e
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1606421
> Commit-Queue: Alexander Cooper <alcooper@chromium.org>
> Reviewed-by: Daniel Cheng <dcheng@chromium.org>
> Reviewed-by: Bill Orr <billorr@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#659625}

TBR=dcheng@chromium.org,bajones@chromium.org,billorr@chromium.org,alcooper@chromium.org

Change-Id: Ia5b987d3e4e5746d94a65cd2e8786012345b8c5d
No-Presubmit: true
No-Try: true
Bug: 960978
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1613557
Commit-Queue: Alexander Cooper <alcooper@chromium.org>
Reviewed-by: default avatarAlexander Cooper <alcooper@chromium.org>
Cr-Commit-Position: refs/heads/master@{#660016}
parent 999b1709
...@@ -148,30 +148,7 @@ class WebXrControllerInputMock : public MockXRDeviceHookBase { ...@@ -148,30 +148,7 @@ class WebXrControllerInputMock : public MockXRDeviceHookBase {
return ConnectController(controller); return ConnectController(controller);
} }
void UpdateControllerSupport(
unsigned int controller_index,
const std::map<vr::EVRButtonId, unsigned int>& axis_types,
uint64_t supported_buttons) {
auto controller_data = GetCurrentControllerData(controller_index);
for (unsigned int i = 0; i < device::kMaxNumAxes; i++) {
auto button_id = GetAxisId(i);
auto it = axis_types.find(button_id);
unsigned int new_axis_type = k_eControllerAxis_None;
if (it != axis_types.end())
new_axis_type = it->second;
controller_data.axis_data[i].axis_type = new_axis_type;
}
controller_data.supported_buttons = supported_buttons;
UpdateControllerAndWait(controller_index, controller_data);
}
private: private:
vr::EVRButtonId GetAxisId(unsigned int offset) {
return static_cast<vr::EVRButtonId>(vr::k_EButton_Axis0 + offset);
}
unsigned int GetAxisOffset(vr::EVRButtonId button_id) { unsigned int GetAxisOffset(vr::EVRButtonId button_id) {
DCHECK(vr::k_EButton_Axis0 <= button_id && DCHECK(vr::k_EButton_Axis0 <= button_id &&
button_id < (vr::k_EButton_Axis0 + device::kMaxNumAxes)); button_id < (vr::k_EButton_Axis0 + device::kMaxNumAxes));
...@@ -200,78 +177,6 @@ void WebXrControllerInputMock::OnFrameSubmitted( ...@@ -200,78 +177,6 @@ void WebXrControllerInputMock::OnFrameSubmitted(
std::move(callback).Run(); std::move(callback).Run();
} }
// Ensure that changes to a gamepad object respect that it is the same object
// and that if whether or not an input source has a gamepad changes that the
// input source change event is fired and a new input source is created.
IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, TestInputGamepadSameObject) {
WebXrControllerInputMock my_mock;
// Create a set of buttons and axes that don't have enough data to be made
// into an xr-standard gamepad (which we expect the runtimes to not report).
// Note that we need to set the trigger axis because of how OpenVR handles
// selects.
uint64_t insufficient_buttons =
vr::ButtonMaskFromId(vr::k_EButton_SteamVR_Trigger);
std::map<vr::EVRButtonId, unsigned int> insufficient_axis_types = {
{vr::k_EButton_SteamVR_Trigger, vr::k_eControllerAxis_Trigger},
};
// Create a set of buttons and axes that we expect to have enough data to be
// made into an xr-standard gamepad (which we expect the runtimes to report).
uint64_t sufficient_buttons =
vr::ButtonMaskFromId(vr::k_EButton_SteamVR_Trigger) |
vr::ButtonMaskFromId(vr::k_EButton_Axis0);
std::map<vr::EVRButtonId, unsigned int> sufficient_axis_types = {
{vr::k_EButton_Axis0, vr::k_eControllerAxis_TrackPad},
{vr::k_EButton_SteamVR_Trigger, vr::k_eControllerAxis_Trigger},
};
// Start off without a gamepad.
unsigned int controller_index = my_mock.CreateAndConnectController(
device::ControllerRole::kControllerRoleRight, insufficient_axis_types,
insufficient_buttons);
LoadUrlAndAwaitInitialization(
GetFileUrlForHtmlTestFile("test_webxr_input_same_object"));
EnterSessionWithUserGestureOrFail();
// We should only have seen the first change indicating we have input sources.
PollJavaScriptBooleanOrFail("inputChangeEvents === 1", kPollTimeoutShort);
// We only expect one input source, cache it.
RunJavaScriptOrFail("validateInputSourceLength(1)");
RunJavaScriptOrFail("updateCachedInputSource(0)");
// Toggle a button and confirm that the controller is still the same.
my_mock.PressReleasePrimaryTrigger(controller_index);
RunJavaScriptOrFail("validateCachedSourcePresence(true)");
RunJavaScriptOrFail("validateCurrentAndCachedGamepadMatch()");
// Update the controller to now support a gamepad and verify that we get a
// change event and that the old controller isn't present. Then cache the new
// one.
my_mock.UpdateControllerSupport(controller_index, sufficient_axis_types,
sufficient_buttons);
PollJavaScriptBooleanOrFail("inputChangeEvents === 2", kPollTimeoutShort);
RunJavaScriptOrFail("validateCachedSourcePresence(false)");
RunJavaScriptOrFail("validateInputSourceLength(1)");
RunJavaScriptOrFail("updateCachedInputSource(0)");
// Toggle a button and confirm that the controller is still the same.
my_mock.PressReleasePrimaryTrigger(controller_index);
RunJavaScriptOrFail("validateCachedSourcePresence(true)");
RunJavaScriptOrFail("validateCurrentAndCachedGamepadMatch()");
// Switch back to the insufficient gamepad and confirm that we get the change.
my_mock.UpdateControllerSupport(controller_index, insufficient_axis_types,
insufficient_buttons);
PollJavaScriptBooleanOrFail("inputChangeEvents === 3", kPollTimeoutShort);
RunJavaScriptOrFail("validateCachedSourcePresence(false)");
RunJavaScriptOrFail("validateInputSourceLength(1)");
RunJavaScriptOrFail("done()");
EndTest();
}
// Ensure that if the controller lacks enough data to be considered a Gamepad // Ensure that if the controller lacks enough data to be considered a Gamepad
// that the input source that it is associated with does not have a Gamepad. // that the input source that it is associated with does not have a Gamepad.
IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, TestGamepadIncompleteData) { IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, TestGamepadIncompleteData) {
...@@ -284,12 +189,12 @@ IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, TestGamepadIncompleteData) { ...@@ -284,12 +189,12 @@ IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, TestGamepadIncompleteData) {
my_mock.CreateAndConnectController( my_mock.CreateAndConnectController(
device::ControllerRole::kControllerRoleRight, {}, supported_buttons); device::ControllerRole::kControllerRoleRight, {}, supported_buttons);
LoadUrlAndAwaitInitialization( this->LoadUrlAndAwaitInitialization(
GetFileUrlForHtmlTestFile("test_webxr_gamepad_support")); this->GetFileUrlForHtmlTestFile("test_webxr_gamepad_support"));
EnterSessionWithUserGestureOrFail(); this->EnterSessionWithUserGestureOrFail();
ExecuteStepAndWait("validateInputSourceHasNoGamepad()"); this->ExecuteStepAndWait("validateInputSourceHasNoGamepad()");
RunJavaScriptOrFail("done()"); this->RunJavaScriptOrFail("done()");
EndTest(); this->EndTest();
} }
// Ensure that if a Gamepad has the minimum required number of axes/buttons to // Ensure that if a Gamepad has the minimum required number of axes/buttons to
...@@ -299,9 +204,9 @@ IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, TestGamepadMinimumData) { ...@@ -299,9 +204,9 @@ IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, TestGamepadMinimumData) {
WebXrControllerInputMock my_mock; WebXrControllerInputMock my_mock;
unsigned int controller_index = my_mock.CreateAndConnectMinimalGamepad(); unsigned int controller_index = my_mock.CreateAndConnectMinimalGamepad();
LoadUrlAndAwaitInitialization( this->LoadUrlAndAwaitInitialization(
GetFileUrlForHtmlTestFile("test_webxr_gamepad_support")); this->GetFileUrlForHtmlTestFile("test_webxr_gamepad_support"));
EnterSessionWithUserGestureOrFail(); this->EnterSessionWithUserGestureOrFail();
// Press the trigger and set the axis to a non-zero amount, so we can ensure // Press the trigger and set the axis to a non-zero amount, so we can ensure
// we aren't getting just default gamepad data. // we aren't getting just default gamepad data.
...@@ -341,9 +246,9 @@ IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, TestGamepadCompleteData) { ...@@ -341,9 +246,9 @@ IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, TestGamepadCompleteData) {
device::ControllerRole::kControllerRoleRight, axis_types, device::ControllerRole::kControllerRoleRight, axis_types,
supported_buttons); supported_buttons);
LoadUrlAndAwaitInitialization( this->LoadUrlAndAwaitInitialization(
GetFileUrlForHtmlTestFile("test_webxr_gamepad_support")); this->GetFileUrlForHtmlTestFile("test_webxr_gamepad_support"));
EnterSessionWithUserGestureOrFail(); this->EnterSessionWithUserGestureOrFail();
// Setup some state on the optional buttons (as TestGamepadMinimumData should // Setup some state on the optional buttons (as TestGamepadMinimumData should
// ensure proper state on the required buttons). // ensure proper state on the required buttons).
...@@ -362,18 +267,18 @@ IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, TestGamepadCompleteData) { ...@@ -362,18 +267,18 @@ IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, TestGamepadCompleteData) {
ExecuteStepAndWait("validateMapping('xr-standard')"); ExecuteStepAndWait("validateMapping('xr-standard')");
// The secondary set of axes should be set appropriately. // The secondary set of axes should be set appropriately.
ExecuteStepAndWait("validateAxesValues(1, 0.25, -0.25)"); this->ExecuteStepAndWait("validateAxesValues(1, 0.25, -0.25)");
// Button 2 is reserved for the Grip, and should be pressed. // Button 2 is reserved for the Grip, and should be pressed.
ExecuteStepAndWait("validateButtonPressed(2)"); this->ExecuteStepAndWait("validateButtonPressed(2)");
// Button 3 is reserved for the secondary trackpad/joystick and should be // Button 3 is reserved for the secondary trackpad/joystick and should be
// touched but not pressed. // touched but not pressed.
ExecuteStepAndWait("validateButtonNotPressed(3)"); this->ExecuteStepAndWait("validateButtonNotPressed(3)");
ExecuteStepAndWait("validateButtonTouched(3)"); this->ExecuteStepAndWait("validateButtonTouched(3)");
RunJavaScriptOrFail("done()"); this->RunJavaScriptOrFail("done()");
EndTest(); this->EndTest();
} }
// Ensure that if a Gamepad has all required buttons, an extra button not // Ensure that if a Gamepad has all required buttons, an extra button not
...@@ -399,9 +304,9 @@ IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, TestGamepadReservedData) { ...@@ -399,9 +304,9 @@ IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, TestGamepadReservedData) {
device::ControllerRole::kControllerRoleRight, axis_types, device::ControllerRole::kControllerRoleRight, axis_types,
supported_buttons); supported_buttons);
LoadUrlAndAwaitInitialization( this->LoadUrlAndAwaitInitialization(
GetFileUrlForHtmlTestFile("test_webxr_gamepad_support")); this->GetFileUrlForHtmlTestFile("test_webxr_gamepad_support"));
EnterSessionWithUserGestureOrFail(); this->EnterSessionWithUserGestureOrFail();
// Claim that all buttons are pressed, note that any non-supported buttons // Claim that all buttons are pressed, note that any non-supported buttons
// should be ignored. // should be ignored.
...@@ -431,12 +336,13 @@ IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, ...@@ -431,12 +336,13 @@ IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard,
unsigned int controller_index = my_mock.CreateAndConnectMinimalGamepad(); unsigned int controller_index = my_mock.CreateAndConnectMinimalGamepad();
// Load the test page and enter presentation. // Load the test page and enter presentation.
LoadUrlAndAwaitInitialization(GetFileUrlForHtmlTestFile("test_webxr_input")); this->LoadUrlAndAwaitInitialization(
EnterSessionWithUserGestureOrFail(); this->GetFileUrlForHtmlTestFile("test_webxr_input"));
this->EnterSessionWithUserGestureOrFail();
unsigned int num_iterations = 10; unsigned int num_iterations = 10;
RunJavaScriptOrFail("stepSetupListeners(" + this->RunJavaScriptOrFail("stepSetupListeners(" +
base::NumberToString(num_iterations) + ")"); std::to_string(num_iterations) + ")");
// Press and unpress the controller's trigger a bunch of times and make sure // Press and unpress the controller's trigger a bunch of times and make sure
// they're all registered. // they're all registered.
...@@ -444,9 +350,9 @@ IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, ...@@ -444,9 +350,9 @@ IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard,
my_mock.PressReleasePrimaryTrigger(controller_index); my_mock.PressReleasePrimaryTrigger(controller_index);
// After each trigger release, wait for the JavaScript to receive the // After each trigger release, wait for the JavaScript to receive the
// "select" event. // "select" event.
WaitOnJavaScriptStep(); this->WaitOnJavaScriptStep();
} }
EndTest(); this->EndTest();
} }
// Test that OpenVR controller input is registered via the Gamepad API. // Test that OpenVR controller input is registered via the Gamepad API.
...@@ -469,9 +375,9 @@ IN_PROC_BROWSER_TEST_F(WebVrBrowserTestStandard, ...@@ -469,9 +375,9 @@ IN_PROC_BROWSER_TEST_F(WebVrBrowserTestStandard,
unsigned int controller_index = my_mock.ConnectController(controller_data); unsigned int controller_index = my_mock.ConnectController(controller_data);
// Load the test page and enter presentation. // Load the test page and enter presentation.
LoadUrlAndAwaitInitialization( this->LoadUrlAndAwaitInitialization(
GetFileUrlForHtmlTestFile("test_gamepad_button")); this->GetFileUrlForHtmlTestFile("test_gamepad_button"));
EnterSessionWithUserGestureOrFail(); this->EnterSessionWithUserGestureOrFail();
// We need to have this, otherwise the JavaScript side of the Gamepad API // We need to have this, otherwise the JavaScript side of the Gamepad API
// doesn't seem to pick up the correct button state? I.e. if we don't have // doesn't seem to pick up the correct button state? I.e. if we don't have
...@@ -484,13 +390,13 @@ IN_PROC_BROWSER_TEST_F(WebVrBrowserTestStandard, ...@@ -484,13 +390,13 @@ IN_PROC_BROWSER_TEST_F(WebVrBrowserTestStandard,
// flakiness workaround. Coincidentally, it's also helpful for the different // flakiness workaround. Coincidentally, it's also helpful for the different
// issue solved by the above PressReleasePrimaryTrigger, so make sure to set // issue solved by the above PressReleasePrimaryTrigger, so make sure to set
// it here so that the above press/release isn't caught by the test code. // it here so that the above press/release isn't caught by the test code.
RunJavaScriptOrFail("canStartTest = true"); this->RunJavaScriptOrFail("canStartTest = true");
// Press and release the trigger, ensuring the Gamepad API detects both. // Press and release the trigger, ensuring the Gamepad API detects both.
my_mock.TogglePrimaryTrigger(controller_index); my_mock.TogglePrimaryTrigger(controller_index);
WaitOnJavaScriptStep(); this->WaitOnJavaScriptStep();
my_mock.TogglePrimaryTrigger(controller_index); my_mock.TogglePrimaryTrigger(controller_index);
WaitOnJavaScriptStep(); this->WaitOnJavaScriptStep();
EndTest(); this->EndTest();
} }
class WebXrHeadPoseMock : public MockXRDeviceHookBase { class WebXrHeadPoseMock : public MockXRDeviceHookBase {
......
<!doctype html>
<!--
A collection of helper functions and listeners to confirm the state of input
sources for the same object tests.
-->
<html>
<head>
<link rel="stylesheet" type="text/css" href="../resources/webxr_e2e.css">
</head>
<body>
<canvas id="webgl-canvas"></canvas>
<script src="../../../../../../third_party/blink/web_tests/resources/testharness.js"></script>
<script src="../resources/webxr_e2e.js"></script>
<script src="../resources/webxr_boilerplate.js"></script>
<script>
let inputChangeEvents = 0;
function onInputSourcesChange() {
inputChangeEvents++;
}
onSessionStartedCallback = function(session) {
if (session.mode === "immersive-vr") {
session.addEventListener('inputsourceschange', onInputSourcesChange, false);
}
}
function getCurrentInputSources() {
let currentSession = sessionInfos[sessionTypes.IMMERSIVE].currentSession;
return currentSession.getInputSources();
}
let cached_input_source = null;
function updateCachedInputSource(id) {
let input_sources = getCurrentInputSources();
assert_less_than(id, input_sources.length);
cached_input_source = input_sources[id];
}
function validateCachedSourcePresence(present) {
assert_not_equals(cached_input_source, null);
assert_not_equals(present, undefined);
let current_sources = getCurrentInputSources();
assert_equals(current_sources.includes(cached_input_source), present);
}
function validateInputSourceLength(length) {
assert_equals(getCurrentInputSources().length, length);
}
function validateCurrentAndCachedGamepadMatch() {
assert_not_equals(cached_input_source, null);
let current_sources = getCurrentInputSources();
let index = current_sources.indexOf(cached_input_source);
assert_not_equals(index, -1);
assert_equals(cached_input_source.gamepad, current_sources[index].gamepad);
}
</script>
</body>
</html>
...@@ -13,99 +13,6 @@ ...@@ -13,99 +13,6 @@
namespace blink { namespace blink {
namespace {
// TODO(https://crbug.com/962712): Switch to use typemapping instead.
XRInputSource::TargetRayMode MojomToBlinkTargetRayMode(
device::mojom::XRTargetRayMode target_ray_mode) {
switch (target_ray_mode) {
case device::mojom::XRTargetRayMode::GAZING:
return XRInputSource::TargetRayMode::kGaze;
case device::mojom::XRTargetRayMode::POINTING:
return XRInputSource::TargetRayMode::kTrackedPointer;
case device::mojom::XRTargetRayMode::TAPPING:
return XRInputSource::TargetRayMode::kScreen;
}
NOTREACHED();
}
// TODO(https://crbug.com/962712): Switch to use typemapping instead.
XRInputSource::Handedness MojomToBlinkHandedness(
device::mojom::XRHandedness handedness) {
switch (handedness) {
case device::mojom::XRHandedness::NONE:
return XRInputSource::Handedness::kHandNone;
case device::mojom::XRHandedness::LEFT:
return XRInputSource::Handedness::kHandLeft;
case device::mojom::XRHandedness::RIGHT:
return XRInputSource::Handedness::kHandRight;
}
NOTREACHED();
}
} // anonymous namespace
XRInputSource* XRInputSource::CreateOrUpdateFrom(
XRInputSource* other,
XRSession* session,
const device::mojom::blink::XRInputSourceStatePtr& state) {
if (!state)
return other;
XRInputSource* updated_source = other;
if (other && other->InvalidatesSameObject(state)) {
updated_source = MakeGarbageCollected<XRInputSource>(*other);
// Need to explicitly override any of the properties that could cause us to
// recreate the object.
// TODO(https://crbug.com/962724): Simplify this creation pattern
if (state->gamepad) {
updated_source->gamepad_ = MakeGarbageCollected<Gamepad>(
updated_source, 0, updated_source->base_timestamp_, TimeTicks::Now());
} else {
updated_source->gamepad_ = nullptr;
}
} else if (!other) {
updated_source = MakeGarbageCollected<XRInputSource>(session, state);
}
if (state->gamepad) {
updated_source->UpdateGamepad(*(state->gamepad));
}
// Update the input source's description if this state update includes them.
if (state->description) {
const device::mojom::blink::XRInputSourceDescriptionPtr& desc =
state->description;
updated_source->SetTargetRayMode(
MojomToBlinkTargetRayMode(desc->target_ray_mode));
updated_source->SetHandedness(MojomToBlinkHandedness(desc->handedness));
updated_source->SetEmulatedPosition(desc->emulated_position);
if (desc->pointer_offset && desc->pointer_offset->matrix.has_value()) {
const WTF::Vector<float>& m = desc->pointer_offset->matrix.value();
std::unique_ptr<TransformationMatrix> pointer_matrix =
std::make_unique<TransformationMatrix>(
m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10],
m[11], m[12], m[13], m[14], m[15]);
updated_source->SetPointerTransformMatrix(std::move(pointer_matrix));
}
}
if (state->grip && state->grip->matrix.has_value()) {
const Vector<float>& m = state->grip->matrix.value();
std::unique_ptr<TransformationMatrix> grip_matrix =
std::make_unique<TransformationMatrix>(
m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10],
m[11], m[12], m[13], m[14], m[15]);
updated_source->SetBasePoseMatrix(std::move(grip_matrix));
}
return updated_source;
}
XRInputSource::XRInputSource(XRSession* session, uint32_t source_id) XRInputSource::XRInputSource(XRSession* session, uint32_t source_id)
: session_(session), : session_(session),
source_id_(source_id), source_id_(source_id),
...@@ -116,39 +23,6 @@ XRInputSource::XRInputSource(XRSession* session, uint32_t source_id) ...@@ -116,39 +23,6 @@ XRInputSource::XRInputSource(XRSession* session, uint32_t source_id)
SetHandedness(kHandNone); SetHandedness(kHandNone);
} }
XRInputSource::XRInputSource(
XRSession* session,
const device::mojom::blink::XRInputSourceStatePtr& state)
: XRInputSource(session, state->source_id) {
if (state->gamepad) {
gamepad_ = MakeGarbageCollected<Gamepad>(this, 0, base_timestamp_,
TimeTicks::Now());
}
}
// Deep copy because of the unique_ptrs
XRInputSource::XRInputSource(const XRInputSource& other)
: active_frame_id(other.active_frame_id),
primary_input_pressed(other.primary_input_pressed),
selection_cancelled(other.selection_cancelled),
session_(other.session_),
source_id_(other.source_id_),
target_ray_space_(other.target_ray_space_),
grip_space_(other.grip_space_),
gamepad_(other.gamepad_),
emulated_position_(other.emulated_position_),
base_timestamp_(other.base_timestamp_) {
// Since these setters also set strings, for convenience, setting them via
// their existing setters.
SetTargetRayMode(other.target_ray_mode_);
SetHandedness(other.handedness_);
base_pose_matrix_ =
std::make_unique<TransformationMatrix>(*(other.base_pose_matrix_.get()));
pointer_transform_matrix_ = std::make_unique<TransformationMatrix>(
*(other.pointer_transform_matrix_.get()));
}
XRSpace* XRInputSource::gripSpace() const { XRSpace* XRInputSource::gripSpace() const {
if (target_ray_mode_ == kTrackedPointer) { if (target_ray_mode_ == kTrackedPointer) {
return grip_space_; return grip_space_;
...@@ -165,20 +39,6 @@ Gamepad* XRInputSource::gamepad() const { ...@@ -165,20 +39,6 @@ Gamepad* XRInputSource::gamepad() const {
return gamepad_; return gamepad_;
} }
bool XRInputSource::InvalidatesSameObject(
const device::mojom::blink::XRInputSourceStatePtr& state) {
if ((state->gamepad && !gamepad_) || (!state->gamepad && gamepad_)) {
return true;
}
return false;
}
void XRInputSource::UpdateGamepad(const device::Gamepad& gamepad) {
DCHECK(gamepad_);
gamepad_->UpdateFromDeviceState(gamepad);
}
void XRInputSource::SetTargetRayMode(TargetRayMode target_ray_mode) { void XRInputSource::SetTargetRayMode(TargetRayMode target_ray_mode) {
if (target_ray_mode_ == target_ray_mode) if (target_ray_mode_ == target_ray_mode)
return; return;
...@@ -238,6 +98,23 @@ void XRInputSource::SetPointerTransformMatrix( ...@@ -238,6 +98,23 @@ void XRInputSource::SetPointerTransformMatrix(
pointer_transform_matrix_ = std::move(pointer_transform_matrix); pointer_transform_matrix_ = std::move(pointer_transform_matrix);
} }
// TODO(https://crbug.com/955101): Should Gamepad objects be updated in-place,
// or should a new object be created on every call?
void XRInputSource::SetGamepad(const base::Optional<device::Gamepad> gamepad) {
if (gamepad) {
if (!gamepad_) {
// TODO(https://crbug.com/955104): Is the Gamepad object creation time the
// correct time floor?
gamepad_ = MakeGarbageCollected<Gamepad>(this, 0, base_timestamp_,
TimeTicks::Now());
}
gamepad_->UpdateFromDeviceState(*gamepad);
} else {
gamepad_ = nullptr;
}
}
void XRInputSource::Trace(blink::Visitor* visitor) { void XRInputSource::Trace(blink::Visitor* visitor) {
visitor->Trace(session_); visitor->Trace(session_);
visitor->Trace(target_ray_space_); visitor->Trace(target_ray_space_);
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_INPUT_SOURCE_H_ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_INPUT_SOURCE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_INPUT_SOURCE_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_INPUT_SOURCE_H_
#include "device/vr/public/mojom/vr_service.mojom-blink.h"
#include "third_party/blink/renderer/modules/gamepad/gamepad.h" #include "third_party/blink/renderer/modules/gamepad/gamepad.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/heap/handle.h"
...@@ -35,18 +34,9 @@ class XRInputSource : public ScriptWrappable, public Gamepad::Client { ...@@ -35,18 +34,9 @@ class XRInputSource : public ScriptWrappable, public Gamepad::Client {
kHandLeft = 1, kHandLeft = 1,
kHandRight = 2 kHandRight = 2
}; };
enum TargetRayMode { kGaze = 1, kTrackedPointer = 2, kScreen = 3 }; enum TargetRayMode { kGaze = 1, kTrackedPointer = 2, kScreen = 3 };
static XRInputSource* CreateOrUpdateFrom(
XRInputSource* other /* may be null, input */,
XRSession* session,
const device::mojom::blink::XRInputSourceStatePtr& state);
XRInputSource(XRSession*, uint32_t source_id); XRInputSource(XRSession*, uint32_t source_id);
XRInputSource(XRSession*,
const device::mojom::blink::XRInputSourceStatePtr& state);
XRInputSource(const XRInputSource& other);
~XRInputSource() override = default; ~XRInputSource() override = default;
XRSession* session() const { return session_; } XRSession* session() const { return session_; }
...@@ -61,7 +51,11 @@ class XRInputSource : public ScriptWrappable, public Gamepad::Client { ...@@ -61,7 +51,11 @@ class XRInputSource : public ScriptWrappable, public Gamepad::Client {
uint32_t source_id() const { return source_id_; } uint32_t source_id() const { return source_id_; }
void SetTargetRayMode(TargetRayMode); void SetTargetRayMode(TargetRayMode);
void SetHandedness(Handedness);
void SetEmulatedPosition(bool emulated_position);
void SetBasePoseMatrix(std::unique_ptr<TransformationMatrix>);
void SetPointerTransformMatrix(std::unique_ptr<TransformationMatrix>); void SetPointerTransformMatrix(std::unique_ptr<TransformationMatrix>);
void SetGamepad(const base::Optional<device::Gamepad>);
// Gamepad::Client // Gamepad::Client
GamepadHapticActuator* GetVibrationActuatorForGamepad( GamepadHapticActuator* GetVibrationActuatorForGamepad(
...@@ -82,17 +76,6 @@ class XRInputSource : public ScriptWrappable, public Gamepad::Client { ...@@ -82,17 +76,6 @@ class XRInputSource : public ScriptWrappable, public Gamepad::Client {
friend class XRGripSpace; friend class XRGripSpace;
friend class XRTargetRaySpace; friend class XRTargetRaySpace;
void SetHandedness(Handedness);
void SetEmulatedPosition(bool emulated_position);
void SetBasePoseMatrix(std::unique_ptr<TransformationMatrix>);
// Use to check if the updates that would/should be made by a given
// XRInputSourceState would invalidate any SameObject properties guaranteed
// by the idl, and thus require the xr_input_source to be recreated.
bool InvalidatesSameObject(
const device::mojom::blink::XRInputSourceStatePtr& state);
void UpdateGamepad(const device::Gamepad& gamepad);
const Member<XRSession> session_; const Member<XRSession> session_;
const uint32_t source_id_; const uint32_t source_id_;
Member<XRTargetRaySpace> target_ray_space_; Member<XRTargetRaySpace> target_ray_space_;
...@@ -107,12 +90,10 @@ class XRInputSource : public ScriptWrappable, public Gamepad::Client { ...@@ -107,12 +90,10 @@ class XRInputSource : public ScriptWrappable, public Gamepad::Client {
bool emulated_position_ = false; bool emulated_position_ = false;
// TODO(crbug.com/945947): Revisit use of std::unique_ptr.
std::unique_ptr<TransformationMatrix> base_pose_matrix_; std::unique_ptr<TransformationMatrix> base_pose_matrix_;
// This is the transform to apply to the base_pose_matrix_ to get the pointer // This is the transform to apply to the base_pose_matrix_ to get the pointer
// matrix. In most cases it should be static. // matrix. In most cases it should be static.
// TODO(crbug.com/945947): Revisit use of std::unique_ptr.
std::unique_ptr<TransformationMatrix> pointer_transform_matrix_; std::unique_ptr<TransformationMatrix> pointer_transform_matrix_;
// gamepad_ uses this to get relative timestamps. // gamepad_ uses this to get relative timestamps.
......
...@@ -23,5 +23,7 @@ enum XRTargetRayMode { ...@@ -23,5 +23,7 @@ enum XRTargetRayMode {
readonly attribute XRTargetRayMode targetRayMode; readonly attribute XRTargetRayMode targetRayMode;
[SameObject] readonly attribute XRSpace targetRaySpace; [SameObject] readonly attribute XRSpace targetRaySpace;
[SameObject] readonly attribute XRSpace? gripSpace; [SameObject] readonly attribute XRSpace? gripSpace;
[SameObject] readonly attribute Gamepad? gamepad;
// TODO(https://crbug.com/955101): This should be tagged [SameObject].
readonly attribute Gamepad? gamepad;
}; };
...@@ -762,34 +762,28 @@ void XRSession::OnInputStateChange( ...@@ -762,34 +762,28 @@ void XRSession::OnInputStateChange(
int16_t frame_id, int16_t frame_id,
const WTF::Vector<device::mojom::blink::XRInputSourceStatePtr>& const WTF::Vector<device::mojom::blink::XRInputSourceStatePtr>&
input_states) { input_states) {
bool input_sources_changed = false; bool devices_changed = false;
// Update any input sources with new state information. Any updated input // Update any input sources with new state information. Any updated input
// sources are marked as active. // sources are marked as active.
for (const auto& input_state : input_states) { for (const auto& input_state : input_states) {
XRInputSource* stored_input_source = XRInputSource* input_source = input_sources_.at(input_state->source_id);
input_sources_.at(input_state->source_id); if (!input_source) {
XRInputSource* input_source = XRInputSource::CreateOrUpdateFrom( input_source =
stored_input_source, this, input_state); MakeGarbageCollected<XRInputSource>(this, input_state->source_id);
// Using pointer equality to determine if the pointer needs to be set.
if (stored_input_source != input_source) {
input_sources_.Set(input_state->source_id, input_source); input_sources_.Set(input_state->source_id, input_source);
input_sources_changed = true; devices_changed = true;
} }
input_source->active_frame_id = frame_id; input_source->active_frame_id = frame_id;
UpdateSelectState(input_source, input_state); UpdateInputSourceState(input_source, input_state);
} }
// Remove any input sources that are inactive. Note that this is done in // Remove any input sources that are inactive..
// two passes because HeapHashMap makes no guarantees about iterators on
// removal.
std::vector<uint32_t> inactive_sources; std::vector<uint32_t> inactive_sources;
for (const auto& input_source : input_sources_.Values()) { for (const auto& input_source : input_sources_.Values()) {
if (input_source->active_frame_id != frame_id) { if (input_source->active_frame_id != frame_id) {
inactive_sources.push_back(input_source->source_id()); inactive_sources.push_back(input_source->source_id());
input_sources_changed = true; devices_changed = true;
} }
} }
...@@ -799,7 +793,7 @@ void XRSession::OnInputStateChange( ...@@ -799,7 +793,7 @@ void XRSession::OnInputStateChange(
} }
} }
if (input_sources_changed) { if (devices_changed) {
DispatchEvent( DispatchEvent(
*XRSessionEvent::Create(event_type_names::kInputsourceschange, this)); *XRSessionEvent::Create(event_type_names::kInputsourceschange, this));
} }
...@@ -875,12 +869,47 @@ void XRSession::OnPoseReset() { ...@@ -875,12 +869,47 @@ void XRSession::OnPoseReset() {
} }
} }
void XRSession::UpdateSelectState( void XRSession::UpdateInputSourceState(
XRInputSource* input_source, XRInputSource* input_source,
const device::mojom::blink::XRInputSourceStatePtr& state) { const device::mojom::blink::XRInputSourceStatePtr& state) {
if (!input_source || !state) if (!input_source || !state)
return; return;
input_source->SetGamepad(state->gamepad);
// Update the input source's description if this state update
// includes them.
if (state->description) {
const device::mojom::blink::XRInputSourceDescriptionPtr& desc =
state->description;
input_source->SetTargetRayMode(
static_cast<XRInputSource::TargetRayMode>(desc->target_ray_mode));
input_source->SetHandedness(
static_cast<XRInputSource::Handedness>(desc->handedness));
input_source->SetEmulatedPosition(desc->emulated_position);
if (desc->pointer_offset && desc->pointer_offset->matrix.has_value()) {
const WTF::Vector<float>& m = desc->pointer_offset->matrix.value();
std::unique_ptr<TransformationMatrix> pointer_matrix =
std::make_unique<TransformationMatrix>(
m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10],
m[11], m[12], m[13], m[14], m[15]);
input_source->SetPointerTransformMatrix(std::move(pointer_matrix));
}
}
if (state->grip && state->grip->matrix.has_value()) {
const Vector<float>& m = state->grip->matrix.value();
std::unique_ptr<TransformationMatrix> grip_matrix =
std::make_unique<TransformationMatrix>(
m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10],
m[11], m[12], m[13], m[14], m[15]);
input_source->SetBasePoseMatrix(std::move(grip_matrix));
}
// Handle state change of the primary input, which may fire events // Handle state change of the primary input, which may fire events
if (state->primary_input_clicked) if (state->primary_input_clicked)
OnSelect(input_source); OnSelect(input_source);
......
...@@ -192,8 +192,9 @@ class XRSession final : public EventTargetWithInlineData, ...@@ -192,8 +192,9 @@ class XRSession final : public EventTargetWithInlineData,
void UpdateCanvasDimensions(Element*); void UpdateCanvasDimensions(Element*);
void ApplyPendingRenderState(); void ApplyPendingRenderState();
void UpdateSelectState(XRInputSource*, void UpdateInputSourceState(
const device::mojom::blink::XRInputSourceStatePtr&); XRInputSource*,
const device::mojom::blink::XRInputSourceStatePtr&);
XRInputSourceEvent* CreateInputSourceEvent(const AtomicString&, XRInputSourceEvent* CreateInputSourceEvent(const AtomicString&,
XRInputSource*); XRInputSource*);
......
...@@ -510,7 +510,6 @@ _CONFIG = [ ...@@ -510,7 +510,6 @@ _CONFIG = [
'third_party/blink/renderer/modules/device_orientation/', 'third_party/blink/renderer/modules/device_orientation/',
'third_party/blink/renderer/modules/gamepad/', 'third_party/blink/renderer/modules/gamepad/',
'third_party/blink/renderer/modules/sensor/', 'third_party/blink/renderer/modules/sensor/',
'third_party/blink/renderer/modules/xr/',
], ],
'allowed': [ 'allowed': [
'base::subtle::Atomic32', 'base::subtle::Atomic32',
......
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