Commit 0a145e06 authored by Michael Thiessen's avatar Michael Thiessen Committed by Commit Bot

VR: Fix WebVR magic window poses with rotated device.

Starting with gvr 1.13, GVR ignores the screen rotation and always
delivers poses as though the phone was in portrait orientation.
This CL applies the proper rotation to gvr-provided poses to account
for the screen rotation.

Bug: 817889
Change-Id: Ie705046439775b2a34d30b177db6191414acaa10
Reviewed-on: https://chromium-review.googlesource.com/944006
Commit-Queue: Michael Thiessen <mthiesse@chromium.org>
Reviewed-by: default avatarBill Orr <billorr@chromium.org>
Reviewed-by: default avatarIan Vollick <vollick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#540353}
parent d42bbf6f
...@@ -1571,7 +1571,7 @@ void VrShellGl::SendVSync(base::TimeTicks time, GetVSyncCallback callback) { ...@@ -1571,7 +1571,7 @@ void VrShellGl::SendVSync(base::TimeTicks time, GetVSyncCallback callback) {
gfx::Transform head_mat; gfx::Transform head_mat;
device::mojom::VRPosePtr pose = device::mojom::VRPosePtr pose =
device::GvrDelegate::GetVRPosePtrWithNeckModel(gvr_api_.get(), &head_mat, device::GvrDelegate::GetVRPosePtrWithNeckModel(gvr_api_.get(), &head_mat,
prediction_nanos); 0, prediction_nanos);
webvr_head_pose_[frame_index % kPoseRingBufferSize] = head_mat; webvr_head_pose_[frame_index % kPoseRingBufferSize] = head_mat;
webvr_frame_oustanding_[frame_index % kPoseRingBufferSize] = true; webvr_frame_oustanding_[frame_index % kPoseRingBufferSize] = true;
......
...@@ -81,6 +81,12 @@ gfx::Vector3dF GetAngularVelocityFromPoses(gfx::Transform head_mat, ...@@ -81,6 +81,12 @@ gfx::Vector3dF GetAngularVelocityFromPoses(gfx::Transform head_mat,
return omega_vec; return omega_vec;
} }
void PostRotateZ(gfx::Transform* transform, float degrees) {
gfx::Transform rotate;
rotate.RotateAboutZAxis(degrees);
transform->ConcatTransform(rotate);
}
} // namespace } // namespace
/* static */ /* static */
...@@ -134,6 +140,7 @@ void GvrDelegate::GetGvrPoseWithNeckModel(gvr::GvrApi* gvr_api, ...@@ -134,6 +140,7 @@ void GvrDelegate::GetGvrPoseWithNeckModel(gvr::GvrApi* gvr_api,
mojom::VRPosePtr GvrDelegate::GetVRPosePtrWithNeckModel( mojom::VRPosePtr GvrDelegate::GetVRPosePtrWithNeckModel(
gvr::GvrApi* gvr_api, gvr::GvrApi* gvr_api,
gfx::Transform* head_mat_out, gfx::Transform* head_mat_out,
int rotate_degrees,
int64_t prediction_time) { int64_t prediction_time) {
gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow();
target_time.monotonic_system_time_nanos += prediction_time; target_time.monotonic_system_time_nanos += prediction_time;
...@@ -147,6 +154,9 @@ mojom::VRPosePtr GvrDelegate::GetVRPosePtrWithNeckModel( ...@@ -147,6 +154,9 @@ mojom::VRPosePtr GvrDelegate::GetVRPosePtrWithNeckModel(
head_mat_ptr = &head_mat; head_mat_ptr = &head_mat;
GvrMatToTransform(gvr_head_mat, head_mat_ptr); GvrMatToTransform(gvr_head_mat, head_mat_ptr);
if (rotate_degrees != 0)
PostRotateZ(head_mat_ptr, rotate_degrees);
mojom::VRPosePtr pose = GvrDelegate::VRPosePtrFromGvrPose(*head_mat_ptr); mojom::VRPosePtr pose = GvrDelegate::VRPosePtrFromGvrPose(*head_mat_ptr);
// Get a second pose a bit later to calculate angular velocity. // Get a second pose a bit later to calculate angular velocity.
...@@ -156,6 +166,9 @@ mojom::VRPosePtr GvrDelegate::GetVRPosePtrWithNeckModel( ...@@ -156,6 +166,9 @@ mojom::VRPosePtr GvrDelegate::GetVRPosePtrWithNeckModel(
gfx::Transform head_mat_2; gfx::Transform head_mat_2;
GvrMatToTransform(gvr_head_mat_2, &head_mat_2); GvrMatToTransform(gvr_head_mat_2, &head_mat_2);
if (rotate_degrees != 0)
PostRotateZ(&head_mat_2, rotate_degrees);
// Add headset angular velocity to the pose. // Add headset angular velocity to the pose.
pose->angularVelocity.emplace(3); pose->angularVelocity.emplace(3);
double epsilon_seconds = kAngularVelocityEpsilonNanos * 1e-9; double epsilon_seconds = kAngularVelocityEpsilonNanos * 1e-9;
...@@ -171,8 +184,9 @@ mojom::VRPosePtr GvrDelegate::GetVRPosePtrWithNeckModel( ...@@ -171,8 +184,9 @@ mojom::VRPosePtr GvrDelegate::GetVRPosePtrWithNeckModel(
/* static */ /* static */
mojom::VRPosePtr GvrDelegate::GetVRPosePtrWithNeckModel( mojom::VRPosePtr GvrDelegate::GetVRPosePtrWithNeckModel(
gvr::GvrApi* gvr_api, gvr::GvrApi* gvr_api,
gfx::Transform* head_mat_out) { gfx::Transform* head_mat_out,
return GetVRPosePtrWithNeckModel(gvr_api, head_mat_out, int rotate_degrees) {
return GetVRPosePtrWithNeckModel(gvr_api, head_mat_out, rotate_degrees,
kPredictionTimeWithoutVsyncNanos); kPredictionTimeWithoutVsyncNanos);
} }
......
...@@ -33,10 +33,12 @@ class DEVICE_VR_EXPORT GvrDelegate { ...@@ -33,10 +33,12 @@ class DEVICE_VR_EXPORT GvrDelegate {
static mojom::VRPosePtr GetVRPosePtrWithNeckModel( static mojom::VRPosePtr GetVRPosePtrWithNeckModel(
gvr::GvrApi* gvr_api, gvr::GvrApi* gvr_api,
gfx::Transform* head_mat_out, gfx::Transform* head_mat_out,
int rotate_degrees,
int64_t prediction_time); int64_t prediction_time);
static mojom::VRPosePtr GetVRPosePtrWithNeckModel( static mojom::VRPosePtr GetVRPosePtrWithNeckModel(
gvr::GvrApi* gvr_api, gvr::GvrApi* gvr_api,
gfx::Transform* head_mat_out); gfx::Transform* head_mat_out,
int rotate_degrees);
}; };
} // namespace device } // namespace device
......
...@@ -188,8 +188,8 @@ void GvrDevice::ExitPresent() { ...@@ -188,8 +188,8 @@ void GvrDevice::ExitPresent() {
void GvrDevice::OnMagicWindowPoseRequest( void GvrDevice::OnMagicWindowPoseRequest(
mojom::VRMagicWindowProvider::GetPoseCallback callback) { mojom::VRMagicWindowProvider::GetPoseCallback callback) {
std::move(callback).Run( std::move(callback).Run(GvrDelegate::GetVRPosePtrWithNeckModel(
GvrDelegate::GetVRPosePtrWithNeckModel(gvr_api_.get(), nullptr)); gvr_api_.get(), nullptr, rotation_degrees_));
} }
void GvrDevice::OnListeningForActivate(bool listening) { void GvrDevice::OnListeningForActivate(bool listening) {
...@@ -220,6 +220,12 @@ void GvrDevice::OnDIPScaleChanged(JNIEnv* env, const JavaRef<jobject>& obj) { ...@@ -220,6 +220,12 @@ void GvrDevice::OnDIPScaleChanged(JNIEnv* env, const JavaRef<jobject>& obj) {
SetVRDisplayInfo(CreateVRDisplayInfo(gvr_api_.get(), GetId())); SetVRDisplayInfo(CreateVRDisplayInfo(gvr_api_.get(), GetId()));
} }
void GvrDevice::OnRotationChanged(JNIEnv* env,
const JavaRef<jobject>& obj,
jint rotation_degrees) {
rotation_degrees_ = rotation_degrees;
}
void GvrDevice::Activate(mojom::VRDisplayEventReason reason, void GvrDevice::Activate(mojom::VRDisplayEventReason reason,
base::Callback<void(bool)> on_handled) { base::Callback<void(bool)> on_handled) {
OnActivate(reason, std::move(on_handled)); OnActivate(reason, std::move(on_handled));
......
...@@ -38,6 +38,9 @@ class DEVICE_VR_EXPORT GvrDevice : public VRDeviceBase { ...@@ -38,6 +38,9 @@ class DEVICE_VR_EXPORT GvrDevice : public VRDeviceBase {
void OnDIPScaleChanged(JNIEnv* env, void OnDIPScaleChanged(JNIEnv* env,
const base::android::JavaRef<jobject>& obj); const base::android::JavaRef<jobject>& obj);
void OnRotationChanged(JNIEnv* env,
const base::android::JavaRef<jobject>& obj,
jint rotation_degrees);
void Activate(mojom::VRDisplayEventReason reason, void Activate(mojom::VRDisplayEventReason reason,
base::Callback<void(bool)> on_handled); base::Callback<void(bool)> on_handled);
...@@ -59,6 +62,7 @@ class DEVICE_VR_EXPORT GvrDevice : public VRDeviceBase { ...@@ -59,6 +62,7 @@ class DEVICE_VR_EXPORT GvrDevice : public VRDeviceBase {
base::android::ScopedJavaGlobalRef<jobject> non_presenting_context_; base::android::ScopedJavaGlobalRef<jobject> non_presenting_context_;
std::unique_ptr<gvr::GvrApi> gvr_api_; std::unique_ptr<gvr::GvrApi> gvr_api_;
int rotation_degrees_;
base::WeakPtrFactory<GvrDevice> weak_ptr_factory_; base::WeakPtrFactory<GvrDevice> weak_ptr_factory_;
......
...@@ -7,6 +7,7 @@ package org.chromium.device.vr; ...@@ -7,6 +7,7 @@ package org.chromium.device.vr;
import android.content.Context; import android.content.Context;
import android.os.StrictMode; import android.os.StrictMode;
import android.view.Display; import android.view.Display;
import android.view.Surface;
import android.view.WindowManager; import android.view.WindowManager;
import com.google.vr.cardboard.DisplaySynchronizer; import com.google.vr.cardboard.DisplaySynchronizer;
...@@ -46,6 +47,7 @@ public class NonPresentingGvrContext implements DisplayAndroid.DisplayAndroidObs ...@@ -46,6 +47,7 @@ public class NonPresentingGvrContext implements DisplayAndroid.DisplayAndroidObs
} }
mDisplayAndroid = DisplayAndroid.getNonMultiDisplay(context); mDisplayAndroid = DisplayAndroid.getNonMultiDisplay(context);
mDisplayAndroid.addObserver(this); mDisplayAndroid.addObserver(this);
onRotationChanged(mDisplayAndroid.getRotation());
} }
@CalledByNative @CalledByNative
...@@ -69,16 +71,34 @@ public class NonPresentingGvrContext implements DisplayAndroid.DisplayAndroidObs ...@@ -69,16 +71,34 @@ public class NonPresentingGvrContext implements DisplayAndroid.DisplayAndroidObs
mNativeGvrDevice = 0; mNativeGvrDevice = 0;
} }
private int rotationToDegrees(int rotation) {
switch (rotation) {
case Surface.ROTATION_0:
return 0;
case Surface.ROTATION_90:
return 90;
case Surface.ROTATION_180:
return 180;
case Surface.ROTATION_270:
return 270;
}
assert false;
return 0;
}
@Override @Override
public void onRotationChanged(int rotation) {} public void onRotationChanged(int rotation) {
if (mNativeGvrDevice != 0) {
nativeOnRotationChanged(mNativeGvrDevice, rotationToDegrees(rotation));
}
}
@Override @Override
public void onDIPScaleChanged(float dipScale) { public void onDIPScaleChanged(float dipScale) {
mGvrApi.refreshDisplayMetrics(); mGvrApi.refreshDisplayMetrics();
if (mNativeGvrDevice != 0) { if (mNativeGvrDevice != 0) nativeOnDIPScaleChanged(mNativeGvrDevice);
nativeOnDIPScaleChanged(mNativeGvrDevice);
}
} }
private native void nativeOnDIPScaleChanged(long nativeGvrDevice); private native void nativeOnDIPScaleChanged(long nativeGvrDevice);
private native void nativeOnRotationChanged(long nativeGvrDevice, int rotationDegrees);
} }
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