From 1d9c45547709e77d599c218d76317895389db129 Mon Sep 17 00:00:00 2001 From: bajones Date: Fri, 7 Aug 2015 17:57:43 -0700 Subject: [PATCH] Android WebVR implementation, Cardboard 0.5.5 SDK Previously part of https://codereview.chromium.org/829803003/ BUG=389343 Review URL: https://codereview.chromium.org/1200303002 Cr-Commit-Position: refs/heads/master@{#342496} --- build/common.gypi | 11 +- build/config/features.gni | 5 +- content/browser/BUILD.gn | 11 ++ content/browser/android/browser_jni_registrar.cc | 5 + .../vr/android/cardboard/cardboard_vr_device.cc | 153 +++++++++++++++++++++ .../vr/android/cardboard/cardboard_vr_device.h | 38 +++++ .../cardboard/cardboard_vr_device_provider.cc | 29 ++++ .../cardboard/cardboard_vr_device_provider.h | 33 +++++ content/browser/vr/vr_device_manager.cc | 15 +- content/browser/vr/vr_device_manager.h | 6 +- content/browser/vr/vr_device_provider.h | 2 +- content/browser/vr/vr_transform_util.cc | 46 +++++++ content/browser/vr/vr_transform_util.h | 17 +++ content/browser/vr/vr_transform_util_unittest.cc | 63 +++++++++ content/content.gyp | 10 ++ content/content_browser.gypi | 10 ++ content/content_tests.gypi | 6 + content/public/android/BUILD.gn | 11 ++ .../content/browser/input/CardboardVRDevice.java | 88 ++++++++++++ 19 files changed, 548 insertions(+), 11 deletions(-) create mode 100644 content/browser/vr/android/cardboard/cardboard_vr_device.cc create mode 100644 content/browser/vr/android/cardboard/cardboard_vr_device.h create mode 100644 content/browser/vr/android/cardboard/cardboard_vr_device_provider.cc create mode 100644 content/browser/vr/android/cardboard/cardboard_vr_device_provider.h create mode 100644 content/browser/vr/vr_transform_util.cc create mode 100644 content/browser/vr/vr_transform_util.h create mode 100644 content/browser/vr/vr_transform_util_unittest.cc create mode 100644 content/public/android/java/src/org/chromium/content/browser/input/CardboardVRDevice.java diff --git a/build/common.gypi b/build/common.gypi index 29215003f6a0..70ea06c41abc 100644 --- a/build/common.gypi +++ b/build/common.gypi @@ -1034,10 +1034,15 @@ }, { 'pkg-config': 'pkg-config' }], - ], - # WebVR support disabled until platform implementations have been added - 'enable_webvr%': 0, + # Enable WebVR support by default on Android + # Still requires command line flag to access API + ['OS=="android"', { + 'enable_webvr%': 1, + }, { + 'enable_webvr%': 0, + }], + ], # Setting this to '0' will cause V8's startup snapshot to be # embedded in the binary instead of being a external files. diff --git a/build/config/features.gni b/build/config/features.gni index 8ca446dd43d9..c327d998de1b 100644 --- a/build/config/features.gni +++ b/build/config/features.gni @@ -208,5 +208,6 @@ enable_hangout_services_extension = false # Whether to back up data before sync. enable_pre_sync_backup = is_win || is_mac || (is_linux && !is_chromeos) -# WebVR support disabled until platform implementations have been added -enable_webvr = false +# Enable WebVR support by default on Android +# Still requires command line flag to access API +enable_webvr = is_android diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 0c9d65778e95..1a986d4ce93c 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn @@ -504,6 +504,17 @@ source_set("browser") { "vr/vr_device_manager.cc", "vr/vr_device_manager.h", "vr/vr_device_provider.h", + "vr/vr_transform_util.cc", + "vr/vr_transform_util.h", + ] + } + + if (enable_webvr && is_android) { + sources += [ + "vr/android/cardboard/cardboard_vr_device.cc", + "vr/android/cardboard/cardboard_vr_device.h", + "vr/android/cardboard/cardboard_vr_device_provider.cc", + "vr/android/cardboard/cardboard_vr_device_provider.h", ] } } diff --git a/content/browser/android/browser_jni_registrar.cc b/content/browser/android/browser_jni_registrar.cc index 808e3f3ebbc9..43adba8aa2e8 100644 --- a/content/browser/android/browser_jni_registrar.cc +++ b/content/browser/android/browser_jni_registrar.cc @@ -40,6 +40,7 @@ #include "content/browser/screen_orientation/screen_orientation_delegate_android.h" #include "content/browser/speech/speech_recognizer_impl_android.h" #include "content/browser/time_zone_monitor_android.h" +#include "content/browser/vr/android/cardboard/cardboard_vr_device.h" #include "content/browser/web_contents/web_contents_android.h" #include "mojo/android/system/core_impl.h" @@ -52,6 +53,10 @@ base::android::RegistrationMethod kContentRegisteredMethods[] = { {"BrowserAccessibilityManager", content::RegisterBrowserAccessibilityManager}, {"BrowserStartupController", content::RegisterBrowserStartupController}, +#if defined(ENABLE_WEBVR) + {"CardboardVRDevice", + content::CardboardVRDevice::RegisterCardboardVRDevice}, +#endif {"ChildProcessLauncher", content::RegisterChildProcessLauncher}, {"ContentReadbackHandler", content::ContentReadbackHandler::RegisterContentReadbackHandler}, diff --git a/content/browser/vr/android/cardboard/cardboard_vr_device.cc b/content/browser/vr/android/cardboard/cardboard_vr_device.cc new file mode 100644 index 000000000000..28661ea730ce --- /dev/null +++ b/content/browser/vr/android/cardboard/cardboard_vr_device.cc @@ -0,0 +1,153 @@ +// Copyright 2015 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 "content/browser/vr/android/cardboard/cardboard_vr_device.h" + +#include +#include + +#include "base/android/jni_android.h" +#include "base/android/jni_array.h" +#include "base/android/jni_string.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/time/time.h" +#include "base/trace_event/trace_event.h" +#include "content/browser/vr/vr_transform_util.h" +#include "jni/CardboardVRDevice_jni.h" + +using base::android::AttachCurrentThread; + +namespace content { + +bool CardboardVRDevice::RegisterCardboardVRDevice(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +CardboardVRDevice::CardboardVRDevice(VRDeviceProvider* provider) + : VRDevice(provider), frame_index_(0) { + JNIEnv* env = AttachCurrentThread(); + j_cardboard_device_.Reset(Java_CardboardVRDevice_create( + env, base::android::GetApplicationContext())); + j_head_matrix_.Reset(env, env->NewFloatArray(16)); +} + +CardboardVRDevice::~CardboardVRDevice() { + Java_CardboardVRDevice_stopTracking(AttachCurrentThread(), + j_cardboard_device_.obj()); +} + +VRDeviceInfoPtr CardboardVRDevice::GetVRDevice() { + TRACE_EVENT0("input", "CardboardVRDevice::GetVRDevice"); + VRDeviceInfoPtr device = VRDeviceInfo::New(); + + JNIEnv* env = AttachCurrentThread(); + + ScopedJavaLocalRef j_device_name = + Java_CardboardVRDevice_getDeviceName(env, j_cardboard_device_.obj()); + device->deviceName = + base::android::ConvertJavaStringToUTF8(env, j_device_name.obj()); + + ScopedJavaLocalRef j_fov(env, env->NewFloatArray(4)); + Java_CardboardVRDevice_getFieldOfView(env, j_cardboard_device_.obj(), + j_fov.obj()); + + std::vector fov; + base::android::JavaFloatArrayToFloatVector(env, j_fov.obj(), &fov); + + device->hmdInfo = VRHMDInfo::New(); + VRHMDInfoPtr& hmdInfo = device->hmdInfo; + + hmdInfo->leftEye = VREyeParameters::New(); + hmdInfo->rightEye = VREyeParameters::New(); + VREyeParametersPtr& left_eye = hmdInfo->leftEye; + VREyeParametersPtr& right_eye = hmdInfo->rightEye; + + left_eye->recommendedFieldOfView = VRFieldOfView::New(); + left_eye->recommendedFieldOfView->upDegrees = fov[0]; + left_eye->recommendedFieldOfView->downDegrees = fov[1]; + left_eye->recommendedFieldOfView->leftDegrees = fov[2]; + left_eye->recommendedFieldOfView->rightDegrees = fov[3]; + + // Cardboard devices always assume a mirrored FOV, so this is just the left + // eye FOV with the left and right degrees swapped. + right_eye->recommendedFieldOfView = VRFieldOfView::New(); + right_eye->recommendedFieldOfView->upDegrees = fov[0]; + right_eye->recommendedFieldOfView->downDegrees = fov[1]; + right_eye->recommendedFieldOfView->leftDegrees = fov[3]; + right_eye->recommendedFieldOfView->rightDegrees = fov[2]; + + // Cardboard does not support configurable FOV. + left_eye->maximumFieldOfView = left_eye->recommendedFieldOfView.Clone(); + right_eye->maximumFieldOfView = right_eye->recommendedFieldOfView.Clone(); + left_eye->minimumFieldOfView = left_eye->recommendedFieldOfView.Clone(); + right_eye->minimumFieldOfView = right_eye->recommendedFieldOfView.Clone(); + + float ipd = Java_CardboardVRDevice_getIpd(env, j_cardboard_device_.obj()); + + left_eye->eyeTranslation = VRVector3::New(); + left_eye->eyeTranslation->x = ipd * -0.5f; + left_eye->eyeTranslation->y = 0.0f; + left_eye->eyeTranslation->z = 0.0f; + + right_eye->eyeTranslation = VRVector3::New(); + right_eye->eyeTranslation->x = ipd * 0.5f; + right_eye->eyeTranslation->y = 0.0f; + right_eye->eyeTranslation->z = 0.0f; + + ScopedJavaLocalRef j_screen_size(env, env->NewIntArray(2)); + Java_CardboardVRDevice_getScreenSize(env, j_cardboard_device_.obj(), + j_screen_size.obj()); + + std::vector screen_size; + base::android::JavaIntArrayToIntVector(env, j_screen_size.obj(), + &screen_size); + + left_eye->renderRect = VRRect::New(); + left_eye->renderRect->x = 0; + left_eye->renderRect->y = 0; + left_eye->renderRect->width = screen_size[0] / 2.0; + left_eye->renderRect->height = screen_size[1]; + + right_eye->renderRect = VRRect::New(); + right_eye->renderRect->x = screen_size[0] / 2.0; + right_eye->renderRect->y = 0; + right_eye->renderRect->width = screen_size[0] / 2.0; + right_eye->renderRect->height = screen_size[1]; + + return device.Pass(); +} + +VRSensorStatePtr CardboardVRDevice::GetSensorState() { + TRACE_EVENT0("input", "CardboardVRDevice::GetSensorState"); + VRSensorStatePtr state = VRSensorState::New(); + + state->timestamp = base::Time::Now().ToJsTime(); + state->frameIndex = frame_index_++; + + JNIEnv* env = AttachCurrentThread(); + Java_CardboardVRDevice_getSensorState(env, j_cardboard_device_.obj(), + j_head_matrix_.obj()); + + std::vector head_matrix; + base::android::JavaFloatArrayToFloatVector(env, j_head_matrix_.obj(), + &head_matrix); + + state->orientation = MatrixToOrientationQuaternion( + &head_matrix[0], &head_matrix[4], &head_matrix[8]); + + state->position = VRVector3::New(); + state->position->x = -head_matrix[12]; + state->position->y = head_matrix[13]; + state->position->z = head_matrix[14]; + + return state.Pass(); +} + +void CardboardVRDevice::ResetSensor() { + Java_CardboardVRDevice_resetSensor(AttachCurrentThread(), + j_cardboard_device_.obj()); +} + +} // namespace content diff --git a/content/browser/vr/android/cardboard/cardboard_vr_device.h b/content/browser/vr/android/cardboard/cardboard_vr_device.h new file mode 100644 index 000000000000..769fd9af7232 --- /dev/null +++ b/content/browser/vr/android/cardboard/cardboard_vr_device.h @@ -0,0 +1,38 @@ +// Copyright 2015 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 CONTENT_BROWSER_VR_CARDBOARD_VR_DEVICE_H +#define CONTENT_BROWSER_VR_CARDBOARD_VR_DEVICE_H + +#include + +#include "base/android/jni_android.h" +#include "base/basictypes.h" +#include "content/browser/vr/vr_device.h" + +namespace content { + +class CardboardVRDevice : public VRDevice { + public: + static bool RegisterCardboardVRDevice(JNIEnv* env); + + explicit CardboardVRDevice(VRDeviceProvider* provider); + ~CardboardVRDevice() override; + + VRDeviceInfoPtr GetVRDevice() override; + VRSensorStatePtr GetSensorState() override; + void ResetSensor() override; + + private: + base::android::ScopedJavaGlobalRef j_cardboard_device_; + base::android::ScopedJavaGlobalRef j_head_matrix_; + + unsigned int frame_index_; + + DISALLOW_COPY_AND_ASSIGN(CardboardVRDevice); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_VR_CARDBOARD_VR_DEVICE_H diff --git a/content/browser/vr/android/cardboard/cardboard_vr_device_provider.cc b/content/browser/vr/android/cardboard/cardboard_vr_device_provider.cc new file mode 100644 index 000000000000..e3c0f65f23ef --- /dev/null +++ b/content/browser/vr/android/cardboard/cardboard_vr_device_provider.cc @@ -0,0 +1,29 @@ +// Copyright 2015 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 "content/browser/vr/android/cardboard/cardboard_vr_device_provider.h" + +#include "content/browser/vr/android/cardboard/cardboard_vr_device.h" + +namespace content { + +CardboardVRDeviceProvider::CardboardVRDeviceProvider() : VRDeviceProvider() { +} + +CardboardVRDeviceProvider::~CardboardVRDeviceProvider() { +} + +void CardboardVRDeviceProvider::GetDevices(std::vector* devices) { + if (!cardboard_device_) { + cardboard_device_.reset(new CardboardVRDevice(this)); + } + + devices->push_back(cardboard_device_.get()); +} + +void CardboardVRDeviceProvider::Initialize() { + // No initialization needed for Cardboard devices. +} + +} // namespace content diff --git a/content/browser/vr/android/cardboard/cardboard_vr_device_provider.h b/content/browser/vr/android/cardboard/cardboard_vr_device_provider.h new file mode 100644 index 000000000000..2b3f87c2b1e7 --- /dev/null +++ b/content/browser/vr/android/cardboard/cardboard_vr_device_provider.h @@ -0,0 +1,33 @@ +// Copyright 2015 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 CONTENT_BROWSER_VR_CARDBOARD_VR_DEVICE_PROVIDER_H +#define CONTENT_BROWSER_VR_CARDBOARD_VR_DEVICE_PROVIDER_H + +#include + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "content/browser/vr/vr_device.h" +#include "content/browser/vr/vr_device_provider.h" + +namespace content { + +class CardboardVRDeviceProvider : public VRDeviceProvider { + public: + CardboardVRDeviceProvider(); + ~CardboardVRDeviceProvider() override; + + void GetDevices(std::vector* devices) override; + void Initialize() override; + + private: + scoped_ptr cardboard_device_; + + DISALLOW_COPY_AND_ASSIGN(CardboardVRDeviceProvider); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_VR_CARDBOARD_VR_DEVICE_PROVIDER_H diff --git a/content/browser/vr/vr_device_manager.cc b/content/browser/vr/vr_device_manager.cc index 476149c27be1..07e420da38b7 100644 --- a/content/browser/vr/vr_device_manager.cc +++ b/content/browser/vr/vr_device_manager.cc @@ -4,9 +4,14 @@ #include "content/browser/vr/vr_device_manager.h" +#include "base/bind.h" #include "base/memory/singleton.h" #include "third_party/WebKit/public/platform/modules/vr/WebVR.h" +#if defined(OS_ANDROID) +#include "content/browser/vr/android/cardboard/cardboard_vr_device_provider.h" +#endif + namespace content { namespace { @@ -15,8 +20,14 @@ VRDeviceManager* g_vr_device_manager = nullptr; VRDeviceManager::VRDeviceManager() : vr_initialized_(false), keep_alive_(false) { - bindings_.set_error_handler(this); + bindings_.set_connection_error_handler( + base::Bind(&VRDeviceManager::OnConnectionError, base::Unretained(this))); // Register VRDeviceProviders for the current platform +#if defined(OS_ANDROID) + scoped_ptr cardboard_provider( + new CardboardVRDeviceProvider()); + RegisterProvider(cardboard_provider.Pass()); +#endif } VRDeviceManager::VRDeviceManager(scoped_ptr provider) @@ -70,7 +81,7 @@ mojo::Array VRDeviceManager::GetVRDevices() { std::vector devices; for (const auto& provider : providers_) - provider->GetDevices(devices); + provider->GetDevices(&devices); mojo::Array out_devices(0); for (const auto& device : devices) { diff --git a/content/browser/vr/vr_device_manager.h b/content/browser/vr/vr_device_manager.h index 6c8dc9646a8d..58789f767be8 100644 --- a/content/browser/vr/vr_device_manager.h +++ b/content/browser/vr/vr_device_manager.h @@ -20,7 +20,7 @@ namespace content { -class VRDeviceManager : public VRService, public mojo::ErrorHandler { +class VRDeviceManager : public VRService { public: ~VRDeviceManager() override; @@ -51,8 +51,8 @@ class VRDeviceManager : public VRService, public mojo::ErrorHandler { const GetSensorStateCallback& callback) override; void ResetSensor(uint32_t index) override; - // mojo::ErrorHandler implementation - void OnConnectionError() override; + // Mojo connection error handler. + void OnConnectionError(); using ProviderList = std::vector>; ProviderList providers_; diff --git a/content/browser/vr/vr_device_provider.h b/content/browser/vr/vr_device_provider.h index 7a0207ce8005..9a4910a47332 100644 --- a/content/browser/vr/vr_device_provider.h +++ b/content/browser/vr/vr_device_provider.h @@ -16,7 +16,7 @@ class VRDeviceProvider { VRDeviceProvider() {} virtual ~VRDeviceProvider() {} - virtual void GetDevices(std::vector& devices) = 0; + virtual void GetDevices(std::vector* devices) = 0; // If the VR API requires initialization that should happen here. virtual void Initialize() = 0; diff --git a/content/browser/vr/vr_transform_util.cc b/content/browser/vr/vr_transform_util.cc new file mode 100644 index 000000000000..f46955297228 --- /dev/null +++ b/content/browser/vr/vr_transform_util.cc @@ -0,0 +1,46 @@ +// Copyright 2015 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 "content/browser/vr/vr_transform_util.h" + +#include + +namespace content { + +// Source: +// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/ +VRVector4Ptr MatrixToOrientationQuaternion( + const float m0[3], const float m1[3], const float m2[3]) { + VRVector4Ptr out = VRVector4::New(); + float trace = m0[0] + m1[1] + m2[2]; + float root; + if (trace > 0.0f) { + root = sqrtf(1.0f + trace) * 2.0f; + out->x = (m2[1] - m1[2]) / root; + out->y = (m0[2] - m2[0]) / root; + out->z = (m1[0] - m0[1]) / root; + out->w = 0.25f * root; + } else if ((m0[0] > m1[1]) && (m0[0] > m2[2])) { + root = sqrtf(1.0f + m0[0] - m1[1] - m2[2]) * 2.0f; + out->x = 0.25f * root; + out->y = (m0[1] + m1[0]) / root; + out->z = (m0[2] + m2[0]) / root; + out->w = (m2[1] - m1[2]) / root; + } else if (m1[1] > m2[2]) { + root = sqrtf(1.0f + m1[1] - m0[0] - m2[2]) * 2.0f; + out->x = (m0[1] + m1[0]) / root; + out->y = 0.25f * root; + out->z = (m1[2] + m2[1]) / root; + out->w = (m0[2] - m2[0]) / root; + } else { + root = sqrtf(1.0f + m2[2] - m0[0] - m1[1]) * 2.0f; + out->x = (m0[2] + m2[0]) / root; + out->y = (m1[2] + m2[1]) / root; + out->z = 0.25f * root; + out->w = (m1[0] - m0[1]) / root; + } + return out.Pass(); +} + +} // namespace content diff --git a/content/browser/vr/vr_transform_util.h b/content/browser/vr/vr_transform_util.h new file mode 100644 index 000000000000..3ffa7da20605 --- /dev/null +++ b/content/browser/vr/vr_transform_util.h @@ -0,0 +1,17 @@ +// Copyright 2015 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 CONTENT_BROWSER_VR_VR_TRANSFORM_UTILS_H +#define CONTENT_BROWSER_VR_VR_TRANSFORM_UTILS_H + +#include "content/common/vr_service.mojom.h" + +namespace content { + +VRVector4Ptr MatrixToOrientationQuaternion( + const float m0[3], const float m1[3], const float m2[3]); + +} // namespace content + +#endif // CONTENT_BROWSER_VR_VR_TRANSFORM_UTILS_H diff --git a/content/browser/vr/vr_transform_util_unittest.cc b/content/browser/vr/vr_transform_util_unittest.cc new file mode 100644 index 000000000000..3c7728f92f73 --- /dev/null +++ b/content/browser/vr/vr_transform_util_unittest.cc @@ -0,0 +1,63 @@ +// Copyright 2015 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 + +#include "content/browser/vr/vr_transform_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { + +const float kPi = 3.14159265f; + +void EXPECT_QUATERNION( + float x, float y, float z, float w, + const VRVector4Ptr& quat) { + EXPECT_NEAR(x, quat->x, 0.0001f); + EXPECT_NEAR(y, quat->y, 0.0001f); + EXPECT_NEAR(z, quat->z, 0.0001f); + EXPECT_NEAR(w, quat->w, 0.0001f); +} + +TEST(VRTransformUtilTest, IdentityMatrixToQuaternion) { + float matrix[9] = { + 1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 1.0f + }; + + VRVector4Ptr orientation = MatrixToOrientationQuaternion( + &matrix[0], &matrix[3], &matrix[6]); + + EXPECT_QUATERNION(0.0f, 0.0f, 0.0f, 1.0f, orientation); +} + +TEST(VRTransformUtilTest, 90DegXMatrixToQuaternion) { + float rad = kPi * 0.5f; + float matrix[9] = { + 1.0f, 0.0f, 0.0f, + 0.0f, cosf(rad), -sinf(rad), + 0.0f, sinf(rad), cosf(rad) + }; + + VRVector4Ptr orientation = MatrixToOrientationQuaternion( + &matrix[0], &matrix[3], &matrix[6]); + + EXPECT_QUATERNION(0.7071f, 0.0f, 0.0f, 0.7071f, orientation); +} + +TEST(VRTransformUtilTest, 180DegYMatrixToQuaternion) { + float matrix[9] = { + cosf(kPi), 0.0f, sinf(kPi), + 0.0f, 1.0f, 0.0f, + -sinf(kPi), 0.0f, cosf(kPi) + }; + + VRVector4Ptr orientation = MatrixToOrientationQuaternion( + &matrix[0], &matrix[3], &matrix[6]); + + EXPECT_QUATERNION(0.0f, 1.0f, 0.0f, 0.0f, orientation); +} + +} // namespace content diff --git a/content/content.gyp b/content/content.gyp index e8ea97c0b393..2ab5615efdf7 100644 --- a/content/content.gyp +++ b/content/content.gyp @@ -610,6 +610,16 @@ 'motionevent_jni_headers' ], 'includes': [ 'content_jni.gypi' ], + 'conditions': [ + ['enable_webvr==1', { + 'sources': [ + 'public/android/java/src/org/chromium/content/browser/input/CardboardVRDevice.java', + ], + 'dependencies': [ + '../third_party/cardboard-java/cardboard.gyp:cardboard_jar', + ], + }], + ], }, { 'target_name': 'content_icudata', diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 5ce366c0f378..a7d54b0943a6 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -2145,7 +2145,17 @@ 'browser/vr/vr_device_manager.cc', 'browser/vr/vr_device_manager.h', 'browser/vr/vr_device_provider.h', + 'browser/vr/vr_transform_util.cc', + 'browser/vr/vr_transform_util.h', ] }], + ['enable_webvr==1 and OS=="android"', { + 'sources': [ + 'browser/vr/android/cardboard/cardboard_vr_device.cc', + 'browser/vr/android/cardboard/cardboard_vr_device.h', + 'browser/vr/android/cardboard/cardboard_vr_device_provider.cc', + 'browser/vr/android/cardboard/cardboard_vr_device_provider.h', + ], + }], ], } diff --git a/content/content_tests.gypi b/content/content_tests.gypi index b21289b46ffc..0ae8136b0bad 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -763,6 +763,9 @@ 'browser/renderer_host/input/motion_event_android_unittest.cc', 'renderer/java/gin_java_bridge_value_converter_unittest.cc', ], + 'content_unittests_webvr_sources': [ + 'browser/vr/vr_transform_util_unittest.cc', + ], }, 'targets': [ { @@ -1195,6 +1198,9 @@ '../third_party/boringssl/boringssl.gyp:boringssl', ], }], + ['enable_webvr==1', { + 'sources': [ '<@(content_unittests_webvr_sources)' ], + }], ], }, ], diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index fc73050b0d41..81a28c068518 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn @@ -63,6 +63,10 @@ android_library("content_java") { ] DEPRECATED_java_in_dir = "java/src" + + if (enable_webvr) { + deps += [ "//third_party/cardboard-java:cardboard-java" ] + } } java_strings_grd("content_strings_grd") { @@ -157,6 +161,13 @@ generate_jar_jni("jar_jni") { generate_jni("content_jni_headers") { sources = rebase_path(content_jni_gypi_values.sources, "", "../..") jni_package = "content" + + if (enable_webvr) { + sources += [ "//content/public/android/java/src/org/chromium/content/browser/input/CardboardVRDevice.java" ] + deps = [ + "//third_party/cardboard-java:cardboard-java", + ] + } } group("jni") { diff --git a/content/public/android/java/src/org/chromium/content/browser/input/CardboardVRDevice.java b/content/public/android/java/src/org/chromium/content/browser/input/CardboardVRDevice.java new file mode 100644 index 000000000000..3bc6e82f200e --- /dev/null +++ b/content/public/android/java/src/org/chromium/content/browser/input/CardboardVRDevice.java @@ -0,0 +1,88 @@ +// Copyright 2015 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. + +package org.chromium.content.browser.input; + +import android.content.Context; + +import com.google.vrtoolkit.cardboard.CardboardDeviceParams; +import com.google.vrtoolkit.cardboard.FieldOfView; +import com.google.vrtoolkit.cardboard.HeadMountedDisplay; +import com.google.vrtoolkit.cardboard.HeadMountedDisplayManager; +import com.google.vrtoolkit.cardboard.ScreenParams; +import com.google.vrtoolkit.cardboard.sensors.HeadTracker; + +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; + +/** + * This is the implementation of the C++ counterpart CardboardVRDevice. + */ +@JNINamespace("content") +class CardboardVRDevice { + private static final String TAG = "CardboardVRDevice"; + private final HeadMountedDisplayManager mHMDManager; + private final HeadTracker mHeadTracker; + + @CalledByNative + private static CardboardVRDevice create(Context context) { + return new CardboardVRDevice(context); + } + + private CardboardVRDevice(Context context) { + mHMDManager = new HeadMountedDisplayManager(context); + + mHeadTracker = HeadTracker.createFromContext(context); + mHeadTracker.setNeckModelEnabled(true); + mHeadTracker.startTracking(); + } + + @CalledByNative + private void getFieldOfView(float[] outFov) { + HeadMountedDisplay hmd = mHMDManager.getHeadMountedDisplay(); + CardboardDeviceParams deviceParams = hmd.getCardboardDeviceParams(); + FieldOfView fov = deviceParams.getLeftEyeMaxFov(); + outFov[0] = fov.getTop(); + outFov[1] = fov.getBottom(); + outFov[2] = fov.getLeft(); + outFov[3] = fov.getRight(); + } + + @CalledByNative + private float getIpd() { + HeadMountedDisplay hmd = mHMDManager.getHeadMountedDisplay(); + CardboardDeviceParams deviceParams = hmd.getCardboardDeviceParams(); + return deviceParams.getInterLensDistance(); + } + + @CalledByNative + private String getDeviceName() { + HeadMountedDisplay hmd = mHMDManager.getHeadMountedDisplay(); + CardboardDeviceParams deviceParams = hmd.getCardboardDeviceParams(); + return deviceParams.getVendor() + " " + deviceParams.getModel(); + } + + @CalledByNative + private void getScreenSize(int[] outSize) { + HeadMountedDisplay hmd = mHMDManager.getHeadMountedDisplay(); + ScreenParams screenParams = hmd.getScreenParams(); + outSize[0] = screenParams.getWidth(); + outSize[1] = screenParams.getHeight(); + } + + @CalledByNative + private void getSensorState(float[] outMatrix) { + mHeadTracker.getLastHeadView(outMatrix, 0); + } + + @CalledByNative + private void stopTracking() { + mHeadTracker.stopTracking(); + } + + @CalledByNative + private void resetSensor() { + mHeadTracker.resetTracker(); + } +} -- 2.11.4.GIT