Commit cc004c7f authored by Aldo Culquicondor's avatar Aldo Culquicondor Committed by Commit Bot

VR: Add a controller delegate for VrShellGl

A controller delegate is responsible for updating the controller, detect
gestures and produce a model to be sent to the Ui. This CL introduces 2
delegates for VrShellGl, one for production and one for testing.

This is the first step on a major refactoring on which VrShellGl
disappears in favor of a cross platform RenderLoop, composed of platform
specific delegates for each of its functions.

A revert to https://crrev.com/c/1121670 was needed to get the
chrome_public_test_vr_apk built properly.

Bug: 767282, 848494
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:linux_vr;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: Ib68f975ce4e5e39fc7ebb5cf386b400f48039f4e
Reviewed-on: https://chromium-review.googlesource.com/1151623Reviewed-by: default avataragrieve <agrieve@chromium.org>
Reviewed-by: default avatarAmirhossein Simjour <asimjour@chromium.org>
Reviewed-by: default avatarBrian Sheedy <bsheedy@chromium.org>
Reviewed-by: default avatarBill Orr <billorr@chromium.org>
Commit-Queue: Aldo Culquicondor <acondor@chromium.org>
Cr-Commit-Position: refs/heads/master@{#580178}
parent c8d356ef
......@@ -2425,6 +2425,10 @@ if (enable_java_templates) {
rebase_path(invoker.proguard_config_exclusions, root_build_dir)
args += [ "--proguard-config-exclusions=$_rebased_proguard_config_exclusions" ]
}
if (defined(invoker.apk_under_test)) {
args += [ "--mapping=@FileArg($_rebased_build_config:deps_info:proguard_under_test_mapping)" ]
deps += [ "${invoker.apk_under_test}__proguard" ]
}
}
_dex_sources = [ _proguard_output_jar_path ]
_dex_deps = [ ":$_proguard_target" ]
......
......@@ -138,11 +138,6 @@ public class VrBrowserDialogTest {
VrBrowserTransitionUtils.forceEnterVrBrowserOrFail(POLL_TIMEOUT_LONG_MS);
Thread.sleep(VR_ENTRY_SLEEP_MS);
NativeUiUtils.clickElementAndWaitForUiQuiescence(elementName, new PointF(0, 0));
// Technically not necessary, but clicking on native elements causes the laser to originate
// from the head, not the controller, which looks strange. Since the point of most of these
// tests is to verify that things look correct, better to have the laser in a normal
// position before taking screenshots.
NativeUiUtils.revertToRealControllerAndWaitForUiQuiescence();
}
/**
......@@ -259,7 +254,6 @@ public class VrBrowserDialogTest {
captureScreen("JavaScriptConfirm_Visible");
NativeUiUtils.clickFallbackUiNegativeButton();
NativeUiUtils.revertToRealControllerAndWaitForUiQuiescence();
// Ensure the cancel button was clicked.
Assert.assertTrue("JavaScript Confirm's cancel button was not clicked",
mVrBrowserTestFramework.runJavaScriptOrFail("c", POLL_TIMEOUT_SHORT_MS)
......@@ -284,7 +278,6 @@ public class VrBrowserDialogTest {
// Capture image
captureScreen("JavaScriptPrompt_Visible");
NativeUiUtils.clickFallbackUiPositiveButton();
NativeUiUtils.revertToRealControllerAndWaitForUiQuiescence();
// This JavaScript will only run once the prompt has been dismissed, and the return value
// will only be what we expect if the positive button was actually clicked (as opposed to
// canceled).
......@@ -323,4 +316,4 @@ public class VrBrowserDialogTest {
captureScreen("PageInfoAppearsOnSecurityTokenClick_Visible");
mVrBrowserTestFramework.assertNoJavaScriptErrors();
}
}
\ No newline at end of file
}
......@@ -19,7 +19,11 @@ static_library("vr_android") {
"android_vsync_helper.h",
"autocomplete_controller.cc",
"autocomplete_controller.h",
"controller_delegate_for_testing.cc",
"controller_delegate_for_testing.h",
"gl_browser_interface.h",
"gvr_controller_delegate.cc",
"gvr_controller_delegate.h",
"gvr_keyboard_delegate.cc",
"gvr_keyboard_delegate.h",
"gvr_keyboard_shim.cc",
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/android/vr/controller_delegate_for_testing.h"
#include "chrome/browser/vr/input_event.h"
#include "chrome/browser/vr/test/constants.h"
#include "chrome/browser/vr/ui_interface.h"
#include "chrome/browser/vr/ui_scene_constants.h"
#include "chrome/browser/vr/ui_test_input.h"
namespace {
// Laser origin relative to the center of the controller.
constexpr gfx::Point3F kLaserOriginOffset = {0.0f, 0.0f, -0.05f};
// We position the controller in a fixed position (no arm model).
// The location constants are approximations that allow us to have the
// controller and the laser visible on the screenshots.
void SetOriginAndTransform(vr::ControllerModel* model) {
gfx::Transform mat;
mat.Translate3d(vr::kStartControllerPosition);
mat.PreconcatTransform(gfx::Transform(
gfx::Quaternion(vr::kForwardVector, model->laser_direction)));
model->transform = mat;
model->laser_origin = kLaserOriginOffset;
mat.TransformPoint(&model->laser_origin);
}
} // namespace
namespace vr {
ControllerDelegateForTesting::ControllerDelegateForTesting(UiInterface* ui)
: ui_(ui) {
cached_controller_model_.laser_direction = kForwardVector;
SetOriginAndTransform(&cached_controller_model_);
}
ControllerDelegateForTesting::~ControllerDelegateForTesting() = default;
void ControllerDelegateForTesting::QueueControllerActionForTesting(
ControllerTestInput controller_input) {
DCHECK_NE(controller_input.action,
VrControllerTestAction::kRevertToRealController);
ControllerModel controller_model;
auto target_point = ui_->GetTargetPointForTesting(
controller_input.element_name, controller_input.position);
auto direction = (target_point - kStartControllerPosition) - kOrigin;
direction.GetNormalized(&controller_model.laser_direction);
SetOriginAndTransform(&controller_model);
switch (controller_input.action) {
case VrControllerTestAction::kClick:
// Add in the button down action.
controller_model.touchpad_button_state =
UiInputManager::ButtonState::DOWN;
controller_model_queue_.push(controller_model);
// Add in the button up action.
controller_model.touchpad_button_state = UiInputManager::ButtonState::UP;
controller_model_queue_.push(controller_model);
break;
case VrControllerTestAction::kHover:
controller_model_queue_.push(controller_model);
break;
default:
NOTREACHED() << "Given unsupported controller action";
}
}
bool ControllerDelegateForTesting::IsQueueEmpty() const {
return controller_model_queue_.empty();
}
void ControllerDelegateForTesting::UpdateController(
const RenderInfo& render_info,
base::TimeTicks current_time,
bool is_webxr_frame) {
if (!controller_model_queue_.empty()) {
cached_controller_model_ = controller_model_queue_.front();
controller_model_queue_.pop();
}
cached_controller_model_.last_orientation_timestamp = current_time;
cached_controller_model_.last_button_timestamp = current_time;
}
ControllerModel ControllerDelegateForTesting::GetModel(
const RenderInfo& render_info) {
return cached_controller_model_;
}
InputEventList ControllerDelegateForTesting::GetGestures(
base::TimeTicks current_time) {
return InputEventList();
}
device::mojom::XRInputSourceStatePtr
ControllerDelegateForTesting::GetInputSourceState() {
auto state = device::mojom::XRInputSourceState::New();
state->description = device::mojom::XRInputSourceDescription::New();
state->source_id = 1;
state->description->target_ray_mode =
device::mojom::XRTargetRayMode::POINTING;
state->description->emulated_position = true;
return state;
}
void ControllerDelegateForTesting::OnResume() {}
void ControllerDelegateForTesting::OnPause() {}
} // namespace vr
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ANDROID_VR_CONTROLLER_DELEGATE_FOR_TESTING_H_
#define CHROME_BROWSER_ANDROID_VR_CONTROLLER_DELEGATE_FOR_TESTING_H_
#include <queue>
#include "base/macros.h"
#include "chrome/browser/vr/controller_delegate.h"
#include "chrome/browser/vr/model/controller_model.h"
namespace vr {
class UiInterface;
struct ControllerTestInput;
class ControllerDelegateForTesting : public ControllerDelegate {
public:
explicit ControllerDelegateForTesting(UiInterface* ui);
~ControllerDelegateForTesting() override;
void QueueControllerActionForTesting(ControllerTestInput controller_input);
bool IsQueueEmpty() const;
// ControllerDelegate implementation.
void UpdateController(const RenderInfo& render_info,
base::TimeTicks current_time,
bool is_webxr_frame) override;
ControllerModel GetModel(const RenderInfo& render_info) override;
InputEventList GetGestures(base::TimeTicks current_time) override;
device::mojom::XRInputSourceStatePtr GetInputSourceState() override;
void OnResume() override;
void OnPause() override;
private:
UiInterface* ui_;
std::queue<ControllerModel> controller_model_queue_;
ControllerModel cached_controller_model_;
DISALLOW_COPY_AND_ASSIGN(ControllerDelegateForTesting);
};
} // namespace vr
#endif // CHROME_BROWSER_ANDROID_VR_CONTROLLER_DELEGATE_FOR_TESTING_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/android/vr/gvr_controller_delegate.h"
#include <utility>
#include "chrome/browser/android/vr/gl_browser_interface.h"
#include "chrome/browser/vr/input_event.h"
#include "chrome/browser/vr/model/controller_model.h"
#include "chrome/browser/vr/pose_util.h"
#include "chrome/browser/vr/ui_renderer.h"
namespace {
constexpr gfx::Vector3dF kForwardVector = {0.0f, 0.0f, -1.0f};
}
namespace vr {
GvrControllerDelegate::GvrControllerDelegate(
std::unique_ptr<VrController> controller,
GlBrowserInterface* browser)
: controller_(std::move(controller)), browser_(browser) {}
GvrControllerDelegate::~GvrControllerDelegate() = default;
void GvrControllerDelegate::UpdateController(const RenderInfo& render_info,
base::TimeTicks current_time,
bool is_webxr_frame) {
controller_->UpdateState(render_info.head_pose);
device::GvrGamepadData controller_data = controller_->GetGamepadData();
if (!is_webxr_frame)
controller_data.connected = false;
browser_->UpdateGamepadData(controller_data);
}
ControllerModel GvrControllerDelegate::GetModel(const RenderInfo& render_info) {
gfx::Vector3dF head_direction = GetForwardVector(render_info.head_pose);
gfx::Vector3dF controller_direction;
gfx::Quaternion controller_quat;
if (!controller_->IsConnected()) {
// No controller detected, set up a gaze cursor that tracks the forward
// direction.
controller_direction = kForwardVector;
controller_quat = gfx::Quaternion(kForwardVector, head_direction);
} else {
controller_direction = {0.0f, -sin(kErgoAngleOffset),
-cos(kErgoAngleOffset)};
controller_quat = controller_->Orientation();
}
gfx::Transform(controller_quat).TransformVector(&controller_direction);
ControllerModel controller_model;
controller_->GetTransform(&controller_model.transform);
controller_model.touchpad_button_state = UiInputManager::ButtonState::UP;
DCHECK(!(controller_->ButtonUpHappened(PlatformController::kButtonSelect) &&
controller_->ButtonDownHappened(PlatformController::kButtonSelect)))
<< "Cannot handle a button down and up event within one frame.";
if (controller_->ButtonState(gvr::kControllerButtonClick)) {
controller_model.touchpad_button_state = UiInputManager::ButtonState::DOWN;
}
controller_model.app_button_state =
controller_->ButtonState(gvr::kControllerButtonApp)
? UiInputManager::ButtonState::DOWN
: UiInputManager::ButtonState::UP;
controller_model.home_button_state =
controller_->ButtonState(gvr::kControllerButtonHome)
? UiInputManager::ButtonState::DOWN
: UiInputManager::ButtonState::UP;
controller_model.opacity = controller_->GetOpacity();
controller_model.laser_direction = controller_direction;
controller_model.laser_origin = controller_->GetPointerStart();
controller_model.handedness = controller_->GetHandedness();
controller_model.recentered = controller_->GetRecentered();
controller_model.touching_touchpad = controller_->IsTouchingTrackpad();
controller_model.touchpad_touch_position =
controller_->GetPositionInTrackpad();
controller_model.last_orientation_timestamp =
controller_->GetLastOrientationTimestamp();
controller_model.last_button_timestamp =
controller_->GetLastButtonTimestamp();
controller_model.battery_level = controller_->GetBatteryLevel();
return controller_model;
}
InputEventList GvrControllerDelegate::GetGestures(
base::TimeTicks current_time) {
if (!controller_->IsConnected())
return {};
return gesture_detector_.DetectGestures(*controller_, current_time);
}
device::mojom::XRInputSourceStatePtr
GvrControllerDelegate::GetInputSourceState() {
device::mojom::XRInputSourceStatePtr state =
device::mojom::XRInputSourceState::New();
state->description = device::mojom::XRInputSourceDescription::New();
// Only one controller is supported, so the source id can be static.
state->source_id = 1;
// It's a handheld pointing device.
state->description->target_ray_mode =
device::mojom::XRTargetRayMode::POINTING;
// Controller uses an arm model.
state->description->emulated_position = true;
if (controller_->IsConnected()) {
// Set the primary button state.
bool select_button_down =
controller_->IsButtonDown(PlatformController::kButtonSelect);
state->primary_input_pressed = select_button_down;
state->primary_input_clicked =
was_select_button_down_ && !select_button_down;
was_select_button_down_ = select_button_down;
// Set handedness.
state->description->handedness =
controller_->GetHandedness() == PlatformController::kRightHanded
? device::mojom::XRHandedness::RIGHT
: device::mojom::XRHandedness::LEFT;
// Get the grip transform
gfx::Transform grip;
controller_->GetTransform(&grip);
state->grip = grip;
// Set the pointer offset from the grip transform.
gfx::Transform pointer;
controller_->GetRelativePointerTransform(&pointer);
state->description->pointer_offset = pointer;
}
return state;
}
void GvrControllerDelegate::OnResume() {
controller_->OnResume();
}
void GvrControllerDelegate::OnPause() {
controller_->OnPause();
}
} // namespace vr
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ANDROID_VR_GVR_CONTROLLER_DELEGATE_H_
#define CHROME_BROWSER_ANDROID_VR_GVR_CONTROLLER_DELEGATE_H_
#include <memory>
#include "base/macros.h"
#include "chrome/browser/android/vr/vr_controller.h"
#include "chrome/browser/vr/controller_delegate.h"
namespace vr {
class GestureDetector;
class GlBrowserInterface;
class GvrControllerDelegate : public ControllerDelegate {
public:
GvrControllerDelegate(std::unique_ptr<VrController> controller,
GlBrowserInterface* browser);
~GvrControllerDelegate() override;
// ControllerDelegate implementation.
void UpdateController(const RenderInfo& render_info,
base::TimeTicks current_time,
bool is_webxr_frame) override;
ControllerModel GetModel(const RenderInfo& render_info) override;
InputEventList GetGestures(base::TimeTicks current_time) override;
device::mojom::XRInputSourceStatePtr GetInputSourceState() override;
void OnResume() override;
void OnPause() override;
private:
std::unique_ptr<VrController> controller_;
GestureDetector gesture_detector_;
GlBrowserInterface* browser_;
bool was_select_button_down_ = false;
DISALLOW_COPY_AND_ASSIGN(GvrControllerDelegate);
};
} // namespace vr
#endif // CHROME_BROWSER_ANDROID_VR_GVR_CONTROLLER_DELEGATE_H_
......@@ -26,10 +26,6 @@ constexpr float kLaserStartDisplacement = 0.045;
constexpr float kFadeDistanceFromFace = 0.34f;
constexpr float kDeltaAlpha = 3.0f;
// Small deadzone for testing that prevents the controller's head offset from
// being updated every frame on 3DOF devices.
constexpr float kHeadOffsetDeadzone = 0.0005f;
void ClampTouchpadPosition(gfx::PointF* position) {
position->set_x(base::ClampToRange(position->x(), 0.0f, 1.0f));
position->set_y(base::ClampToRange(position->y(), 0.0f, 1.0f));
......@@ -126,54 +122,6 @@ device::GvrGamepadData VrController::GetGamepadData() {
return pad;
}
device::mojom::XRInputSourceStatePtr VrController::GetInputSourceState() {
device::mojom::XRInputSourceStatePtr state =
device::mojom::XRInputSourceState::New();
// Only one controller is supported, so the source id can be static.
state->source_id = 1;
// Set the primary button state.
state->primary_input_pressed = ButtonState(GVR_CONTROLLER_BUTTON_CLICK);
if (ButtonUpHappened(PlatformController::kButtonSelect))
state->primary_input_clicked = true;
state->description = device::mojom::XRInputSourceDescription::New();
// It's a handheld pointing device.
state->description->target_ray_mode =
device::mojom::XRTargetRayMode::POINTING;
// Controller uses an arm model.
state->description->emulated_position = true;
// Set handedness.
switch (handedness_) {
case GVR_CONTROLLER_LEFT_HANDED:
state->description->handedness = device::mojom::XRHandedness::LEFT;
break;
case GVR_CONTROLLER_RIGHT_HANDED:
state->description->handedness = device::mojom::XRHandedness::RIGHT;
break;
default:
state->description->handedness = device::mojom::XRHandedness::NONE;
break;
}
// Get the grip transform
gfx::Transform grip;
GetTransform(&grip);
state->grip = grip;
// Set the pointer offset from the grip transform.
gfx::Transform pointer;
GetRelativePointerTransform(&pointer);
state->description->pointer_offset = pointer;
return state;
}
bool VrController::IsButtonDown(ButtonType type) const {
return controller_state_->GetButtonState(PlatformToGvrButton(type));
}
......@@ -299,25 +247,12 @@ bool VrController::IsConnected() {
return controller_state_->GetConnectionState() == gvr::kControllerConnected;
}
void VrController::EnableDeadzoneForTesting() {
enable_deadzone_ = true;
}
void VrController::UpdateState(const gfx::Transform& head_pose) {
gfx::Transform inv_pose;
if (head_pose.GetInverse(&inv_pose)) {
auto current_head_offset = gfx::Point3F();
inv_pose.TransformPoint(&current_head_offset);
// TODO(https://crbug.com/861807): Remove this once the controller can be
// dirty without necessarily affecting quiescence.
if (enable_deadzone_) {
if (head_offset_.SquaredDistanceTo(current_head_offset) >
kHeadOffsetDeadzone) {
head_offset_ = current_head_offset;
}
} else {
head_offset_ = current_head_offset;
}
head_offset_ = current_head_offset;
}
gvr::Mat4f gvr_head_pose;
......
......@@ -14,7 +14,6 @@
#include "chrome/browser/vr/gesture_detector.h"
#include "chrome/browser/vr/platform_controller.h"
#include "device/vr/android/gvr/gvr_gamepad_data_provider.h"
#include "device/vr/public/mojom/vr_service.mojom.h"
#include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr_types.h"
#include "ui/gfx/geometry/point3_f.h"
#include "ui/gfx/geometry/quaternion.h"
......@@ -48,7 +47,6 @@ class VrController : public PlatformController {
void OnPause();
device::GvrGamepadData GetGamepadData();
device::mojom::XRInputSourceStatePtr GetInputSourceState();
// Called once per frame to update controller state.
void UpdateState(const gfx::Transform& head_pose);
......@@ -86,7 +84,6 @@ class VrController : public PlatformController {
int GetBatteryLevel() const override;
private:
bool GetButtonLongPressFromButtonInfo();
void UpdateTimestamps();
......@@ -125,8 +122,6 @@ class VrController : public PlatformController {
float alpha_value_ = 1.0f;
bool enable_deadzone_ = false;
DISALLOW_COPY_AND_ASSIGN(VrController);
};
......
This diff is collapsed.
......@@ -22,6 +22,7 @@
#include "chrome/browser/vr/content_input_delegate.h"
#include "chrome/browser/vr/fps_meter.h"
#include "chrome/browser/vr/model/controller_model.h"
#include "chrome/browser/vr/render_loop.h"
#include "chrome/browser/vr/sliding_average.h"
#include "chrome/browser/vr/ui_input_manager.h"
#include "chrome/browser/vr/ui_renderer.h"
......@@ -67,7 +68,6 @@ class MailboxToSurfaceBridge;
class ScopedGpuTrace;
class SlidingTimeDeltaAverage;
class UiInterface;
class VrController;
class VrShell;
struct WebVrBounds {
......@@ -97,7 +97,8 @@ struct Viewport {
// This class manages all GLThread owned objects and GL rendering for VrShell.
// It is not threadsafe and must only be used on the GL thread.
class VrShellGl : public device::mojom::XRPresentationProvider,
class VrShellGl : public RenderLoop,
public device::mojom::XRPresentationProvider,
public device::mojom::XRFrameDataProvider {
public:
VrShellGl(GlBrowserInterface* browser_interface,
......@@ -176,7 +177,7 @@ class VrShellGl : public device::mojom::XRPresentationProvider,
bool ResizeForWebVR(int16_t frame_index);
void UpdateSamples();
void UpdateEyeInfos(const gfx::Transform& head_pose,
Viewport& viewport,
const Viewport& viewport,
const gfx::Size& render_size,
RenderInfo* out_render_info);
void UpdateContentViewportTransforms(const gfx::Transform& head_pose);
......@@ -288,6 +289,8 @@ class VrShellGl : public device::mojom::XRPresentationProvider,
bool ui_updated);
void ReportUiActivityResultForTesting(VrUiTestActivityResult result);
std::unique_ptr<ControllerDelegate> controller_delegate_for_testing_;
// samplerExternalOES texture data for WebVR content image.
int webvr_texture_id_ = 0;
int content_texture_id_ = 0;
......@@ -349,15 +352,12 @@ class VrShellGl : public device::mojom::XRPresentationProvider,
int webvr_unstuff_ratelimit_frames_ = 0;
bool cardboard_ = false;
gfx::Quaternion controller_quat_;
gfx::Size content_tex_buffer_size_ = {0, 0};
gfx::Size webvr_surface_size_ = {0, 0};
std::unique_ptr<WebXrPresentationState> webxr_ = nullptr;
std::unique_ptr<UiInterface> ui_;
bool web_vr_mode_ = false;
bool ready_to_draw_ = false;
bool paused_ = true;
......@@ -367,7 +367,6 @@ class VrShellGl : public device::mojom::XRPresentationProvider,
bool cardboard_trigger_pressed_ = false;
bool cardboard_trigger_clicked_ = false;
std::unique_ptr<VrController> controller_;
std::vector<device::mojom::XRInputSourceStatePtr> input_states_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
......@@ -442,9 +441,7 @@ class VrShellGl : public device::mojom::XRPresentationProvider,
std::unique_ptr<PlatformUiInputDelegate> vr_dialog_input_delegate_;
bool showing_vr_dialog_ = false;
std::unique_ptr<UiTestState> ui_test_state_;
std::queue<ControllerModel> test_controller_model_queue_;
ControllerModel cached_test_controller_model_;
bool using_test_controller_model_ = false;
bool using_controller_delegate_for_testing_ = false;
base::WeakPtrFactory<VrShellGl> weak_ptr_factory_;
......
......@@ -224,6 +224,7 @@ source_set("vr_ui") {
component("vr_common") {
sources = [
"browser_ui_interface.h",
"controller_delegate.h",
"fps_meter.cc",
"fps_meter.h",
"gesture_detector.cc",
......@@ -237,6 +238,8 @@ component("vr_common") {
"model/speech_recognition_model.h",
"model/ui_mode.h",
"model/web_vr_model.h",
"render_loop.cc",
"render_loop.h",
"sample_queue.cc",
"sample_queue.h",
"service/browser_xr_device.cc",
......@@ -473,6 +476,7 @@ source_set("vr_test_support") {
sources = [
"test/animation_utils.cc",
"test/animation_utils.h",
"test/constants.cc",
"test/constants.h",
"test/mock_browser_ui_interface.cc",
"test/mock_browser_ui_interface.h",
......
......@@ -3,5 +3,5 @@ include_rules = [
"+cc/base",
"+cc/test",
"+cc/trees",
"+device/vr/openvr/test/fake_openvr_log.h"
"+device/vr/public/mojom"
]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_VR_CONTROLLER_DELEGATE_H_
#define CHROME_BROWSER_VR_CONTROLLER_DELEGATE_H_
#include <memory>
#include <vector>
#include "base/time/time.h"
#include "device/vr/public/mojom/vr_service.mojom.h"
namespace vr {
class InputEvent;
struct ControllerModel;
struct RenderInfo;
using InputEventList = std::vector<std::unique_ptr<InputEvent>>;
// Communicates with the PlatformController to update it and obtain input and
// movement information.
class ControllerDelegate {
public:
virtual ~ControllerDelegate() {}
virtual void UpdateController(const RenderInfo& render_info,
base::TimeTicks current_time,
bool is_webxr_frame) = 0;
virtual ControllerModel GetModel(const RenderInfo& render_info) = 0;
virtual InputEventList GetGestures(base::TimeTicks current_time) = 0;
virtual device::mojom::XRInputSourceStatePtr GetInputSourceState() = 0;
virtual void OnResume() = 0;
virtual void OnPause() = 0;
};
} // namespace vr
#endif // CHROME_BROWSER_VR_CONTROLLER_DELEGATE_H_
......@@ -36,7 +36,6 @@ struct VR_BASE_EXPORT ControllerModel {
bool recentered = false;
PlatformController::Handedness handedness = PlatformController::kRightHanded;
base::TimeTicks last_orientation_timestamp;
base::TimeTicks last_touch_timestamp;
base::TimeTicks last_button_timestamp;
int battery_level = 0;
};
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/vr/render_loop.h"
#include <utility>
#include "base/time/time.h"
#include "chrome/browser/vr/controller_delegate.h"
#include "chrome/browser/vr/input_event.h"
#include "chrome/browser/vr/model/controller_model.h"
#include "chrome/browser/vr/ui_interface.h"
namespace vr {
RenderLoop::RenderLoop(std::unique_ptr<UiInterface> ui) : ui_(std::move(ui)) {}
RenderLoop::~RenderLoop() = default;
void RenderLoop::ProcessControllerInput(const RenderInfo& render_info,
base::TimeTicks current_time,
bool is_webxr_frame) {
DCHECK(controller_delegate_);
DCHECK(ui_);
controller_delegate_->UpdateController(render_info, current_time,
is_webxr_frame);
auto input_event_list = controller_delegate_->GetGestures(current_time);
if (is_webxr_frame) {
ui_->HandleMenuButtonEvents(&input_event_list);
} else {
ReticleModel reticle_model;
ControllerModel controller_model =
controller_delegate_->GetModel(render_info);
ui_->HandleInput(current_time, render_info, controller_model,
&reticle_model, &input_event_list);
ui_->OnControllerUpdated(controller_model, reticle_model);
}
}
} // namespace vr
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_VR_RENDER_LOOP_H_
#define CHROME_BROWSER_VR_RENDER_LOOP_H_
#include <memory>
#include "chrome/browser/vr/vr_export.h"
namespace base {
class TimeTicks;
}
namespace vr {
class ControllerDelegate;
class UiInterface;
struct RenderInfo;
// This abstract class handles all input/output activities during a frame.
// This includes head movement, controller movement and input, audio output and
// rendering of the frame.
// TODO(acondor): Move more functionality cross platform functionality from
// VrShellGl and make this class concrete (http://crbug.com/767282).
class VR_EXPORT RenderLoop {
public:
explicit RenderLoop(std::unique_ptr<UiInterface> ui);
virtual ~RenderLoop();
protected:
void ProcessControllerInput(const RenderInfo& render_info,
base::TimeTicks current_time,
bool is_webxr_frame);
std::unique_ptr<UiInterface> ui_;
std::unique_ptr<ControllerDelegate> controller_delegate_;
};
} // namespace vr
#endif // CHROME_BROWSER_VR_RENDER_LOOP_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/vr/test/constants.h"
namespace vr {
gfx::Transform GetPixelDaydreamProjMatrix() {
static const gfx::Transform pixel_daydream_proj_matrix(
1.03317f, 0.0f, 0.271253f, 0.0f, 0.0f, 0.862458f, -0.0314586f, 0.0f, 0.0f,
0.0f, -1.002f, -0.2002f, 0.0f, 0.0f, -1.0f, 0.0f);
return pixel_daydream_proj_matrix;
}
} // namespace vr
......@@ -12,36 +12,21 @@
namespace vr {
// Proj matrix as used on a Pixel phone with the Daydream headset.
static const gfx::Transform kPixelDaydreamProjMatrix(1.03317f,
0.0f,
0.271253f,
0.0f,
0.0f,
0.862458f,
-0.0314586f,
0.0f,
0.0f,
0.0f,
-1.002f,
-0.2002f,
0.0f,
0.0f,
-1.0f,
0.0f);
static const gfx::Transform kStartHeadPose;
static const gfx::Vector3dF kStartControllerPosition(0.3, -0.3, -0.3);
static const gfx::Vector3dF kForwardVector(0.0f, 0.0f, -1.0f);
static const gfx::Vector3dF kBackwardVector(0.0f, 0.0f, 1.0f);
constexpr float kEpsilon = 1e-5f;
gfx::Transform GetPixelDaydreamProjMatrix();
static constexpr gfx::Transform kStartHeadPose;
static constexpr gfx::Vector3dF kStartControllerPosition(0.3, -0.3, -0.3);
static constexpr gfx::Vector3dF kForwardVector(0.0f, 0.0f, -1.0f);
static constexpr gfx::Vector3dF kBackwardVector(0.0f, 0.0f, 1.0f);
static constexpr float kEpsilon = 1e-5f;
// Resolution of Pixel Phone for one eye.
static const gfx::Size kPixelHalfScreen(960, 1080);
static constexpr gfx::Size kPixelHalfScreen(960, 1080);
static const char* kLoremIpsum100Chars =
static constexpr const char* kLoremIpsum100Chars =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis erat nisl, "
"tempus nec neque at nullam.";
static const char* kLoremIpsum700Chars =
static constexpr const char* kLoremIpsum700Chars =
"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo "
"ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis "
"dis parturient montes, nascetur ridiculus mus. Donec quam felis, "
......
......@@ -559,43 +559,23 @@ void Ui::AcceptDoffPromptForTesting() {
button->OnHoverLeave(base::TimeTicks::Now());
}
void Ui::PerformControllerActionForTesting(
ControllerTestInput controller_input,
std::queue<ControllerModel>& controller_model_queue) {
gfx::Point3F Ui::GetTargetPointForTesting(UserFriendlyElementName element_name,
const gfx::PointF& position) {
auto* target_element = scene()->GetUiElementByName(
UserFriendlyElementNameToUiElementName(controller_input.element_name));
UserFriendlyElementNameToUiElementName(element_name));
DCHECK(target_element) << "Unsupported test element";
// The position to click is provided for a unit square, so scale it to match
// the actual element.
controller_input.position.Scale(target_element->size().width(),
target_element->size().height());
auto target = gfx::Point3F(controller_input.position.x(),
controller_input.position.y(), 0.0f);
auto scaled_position = ScalePoint(position, target_element->size().width(),
target_element->size().height());
gfx::Point3F target(scaled_position.x(), scaled_position.y(), 0.0f);
target_element->ComputeTargetWorldSpaceTransform().TransformPoint(&target);
gfx::Point3F origin;
gfx::Vector3dF direction(target - origin);
// We do hit testing with respect to the eye position (world origin), so we
// need to project the target point into the background.
gfx::Vector3dF direction = target - kOrigin;
direction.GetNormalized(&direction);
ControllerModel controller_model;
controller_model.laser_direction = direction;
controller_model.laser_origin = origin;
switch (controller_input.action) {
case VrControllerTestAction::kClick:
// Add in the button down action
controller_model.touchpad_button_state =
UiInputManager::ButtonState::DOWN;
controller_model_queue.push(controller_model);
// Add in the button up action
controller_model.touchpad_button_state = UiInputManager::ButtonState::UP;
controller_model_queue.push(controller_model);
break;
case VrControllerTestAction::kHover:
controller_model.touchpad_button_state = UiInputManager::ButtonState::UP;
controller_model_queue.push(controller_model);
break;
default:
NOTREACHED() << "Given unsupported controller action";
}
return kOrigin +
gfx::ScaleVector3d(direction, scene()->background_distance());
}
ContentElement* Ui::GetContentElement() {
......
......@@ -7,6 +7,7 @@
#include <memory>
#include <queue>
#include <vector>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
......@@ -156,10 +157,8 @@ class VR_EXPORT Ui : public UiInterface {
void OnContentBoundsChanged(int width, int height) override;
void AcceptDoffPromptForTesting() override;
void PerformControllerActionForTesting(
ControllerTestInput controller_input,
std::queue<ControllerModel>& controller_model_queue) override;
gfx::Point3F GetTargetPointForTesting(UserFriendlyElementName element_name,
const gfx::PointF& position) override;
bool IsContentVisibleAndOpaque() override;
bool IsContentOverlayTextureEmpty() override;
void SetContentUsesQuadLayer(bool uses_quad_buffers) override;
......
......@@ -7,6 +7,7 @@
#include <memory>
#include <queue>
#include <vector>
#include "base/memory/weak_ptr.h"
#include "chrome/browser/vr/browser_ui_interface.h"
......@@ -15,7 +16,10 @@
#include "chrome/browser/vr/ui_element_renderer.h"
#include "chrome/browser/vr/ui_input_manager.h"
#include "chrome/browser/vr/ui_scene.h"
#include "chrome/browser/vr/ui_test_input.h"
namespace gfx {
class Point3F;
}
namespace vr {
......@@ -24,6 +28,7 @@ class PlatformUiInputDelegate;
struct ControllerModel;
struct RenderInfo;
struct ReticleModel;
enum class UserFriendlyElementName;
// This interface represents the methods that should be called by its owner, and
// also serves to make all such methods virtual for the sake of separating a UI
......@@ -75,9 +80,9 @@ class UiInterface : public BrowserUiInterface, public KeyboardUiInterface {
virtual void OnSwapContents(int new_content_id) = 0;
virtual void OnContentBoundsChanged(int width, int height) = 0;
virtual void AcceptDoffPromptForTesting() = 0;
virtual void PerformControllerActionForTesting(
ControllerTestInput controller_input,
std::queue<ControllerModel>& controller_model_queue) = 0;
virtual gfx::Point3F GetTargetPointForTesting(
UserFriendlyElementName element_name,
const gfx::PointF& position) = 0;
virtual bool IsContentVisibleAndOpaque() = 0;
virtual bool IsContentOverlayTextureEmpty() = 0;
virtual void SetContentUsesQuadLayer(bool uses_quad_buffers) = 0;
......
......@@ -38,7 +38,7 @@ TEST_F(UiPixelTest, MAYBE(DrawVrBrowsingMode)) {
// Draw UI.
DrawUi(gfx::Vector3dF(0.0f, 0.0f, -1.0f), gfx::Point3F(0.5f, -0.5f, 0.0f),
UiInputManager::ButtonState::UP, 1.0f, kIdentity, kIdentity,
kPixelDaydreamProjMatrix);
GetPixelDaydreamProjMatrix());
// Read pixels into SkBitmap.
auto bitmap = SaveCurrentFrameBufferToSkBitmap();
......
......@@ -3,10 +3,10 @@
// found in the LICENSE file.
#include "chrome/browser/vr/ui_test_input.h"
#include "chrome/browser/vr/elements/ui_element_name.h"
#include "base/logging.h"
#include "base/macros.h"
#include "chrome/browser/vr/elements/ui_element_name.h"
namespace vr {
......
......@@ -697,14 +697,14 @@ TEST_F(UiTest, PropagateContentBoundsOnStart) {
OnContentScreenBoundsChanged(
SizeFsAreApproximatelyEqual(expected_bounds, kTolerance)));
ui_->OnProjMatrixChanged(kPixelDaydreamProjMatrix);
ui_->OnProjMatrixChanged(GetPixelDaydreamProjMatrix());
OnBeginFrame();
}
TEST_F(UiTest, PropagateContentBoundsOnFullscreen) {
CreateScene(kNotInWebVr);
ui_->OnProjMatrixChanged(kPixelDaydreamProjMatrix);
ui_->OnProjMatrixChanged(GetPixelDaydreamProjMatrix());
ui_->SetFullscreen(true);
gfx::SizeF expected_bounds(0.587874f, 0.330614f);
......@@ -712,7 +712,7 @@ TEST_F(UiTest, PropagateContentBoundsOnFullscreen) {
OnContentScreenBoundsChanged(
SizeFsAreApproximatelyEqual(expected_bounds, kTolerance)));
ui_->OnProjMatrixChanged(kPixelDaydreamProjMatrix);
ui_->OnProjMatrixChanged(GetPixelDaydreamProjMatrix());
OnBeginFrame();
}
......@@ -720,7 +720,7 @@ TEST_F(UiTest, DontPropagateContentBoundsOnNegligibleChange) {
CreateScene(kNotInWebVr);
EXPECT_FALSE(RunForMs(0));
ui_->OnProjMatrixChanged(kPixelDaydreamProjMatrix);
ui_->OnProjMatrixChanged(GetPixelDaydreamProjMatrix());
UiElement* content_quad = scene_->GetUiElementByName(kContentQuad);
gfx::SizeF content_quad_size = content_quad->size();
......@@ -730,7 +730,7 @@ TEST_F(UiTest, DontPropagateContentBoundsOnNegligibleChange) {
EXPECT_CALL(*browser_, OnContentScreenBoundsChanged(testing::_)).Times(0);
ui_->OnProjMatrixChanged(kPixelDaydreamProjMatrix);
ui_->OnProjMatrixChanged(GetPixelDaydreamProjMatrix());
}
TEST_F(UiTest, LoadingIndicatorBindings) {
......
......@@ -15,7 +15,7 @@ TEST(VrGeometryUtilTest, CalculateScreenSize) {
gfx::SizeF size(2.4f, 1.6f);
gfx::SizeF screen_size =
CalculateScreenSize(kPixelDaydreamProjMatrix, 2.5f, size);
CalculateScreenSize(GetPixelDaydreamProjMatrix(), 2.5f, size);
EXPECT_FLOAT_EQ(screen_size.width(), 0.49592164f);
EXPECT_FLOAT_EQ(screen_size.height(), 0.27598655f);
......
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