OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/android/vr_shell/non_presenting_gvr_delegate.h" | 5 #include "chrome/browser/android/vr_shell/non_presenting_gvr_delegate.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
10 #include "chrome/browser/android/vr_shell/vr_shell.h" | 10 #include "chrome/browser/android/vr_shell/vr_shell.h" |
11 #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/
gvr.h" | 11 #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/
gvr.h" |
12 | 12 |
13 namespace vr_shell { | 13 namespace vr_shell { |
14 | 14 |
15 namespace { | 15 namespace { |
16 static constexpr int64_t kPredictionTimeWithoutVsyncNanos = 50000000; | 16 static constexpr int64_t kPredictionTimeWithoutVsyncNanos = 50000000; |
17 } // namespace | 17 } // namespace |
18 | 18 |
19 NonPresentingGvrDelegate::NonPresentingGvrDelegate(gvr_context* context) | 19 NonPresentingGvrDelegate::NonPresentingGvrDelegate(gvr_context* context) |
20 : task_runner_(base::ThreadTaskRunnerHandle::Get()), | 20 : task_runner_(base::ThreadTaskRunnerHandle::Get()), |
21 binding_(this), | 21 binding_(this), |
22 weak_ptr_factory_(this) { | 22 weak_ptr_factory_(this) { |
23 gvr_api_ = gvr::GvrApi::WrapNonOwned(context); | 23 // Context may be null, see VrShellDelegate#createNonPresentingNativeContext |
| 24 // for possible reasons a context could fail to be created. For example, |
| 25 // the user might uninstall apps or clear data after VR support was detected. |
| 26 if (context) |
| 27 gvr_api_ = gvr::GvrApi::WrapNonOwned(context); |
24 } | 28 } |
25 | 29 |
26 NonPresentingGvrDelegate::~NonPresentingGvrDelegate() { | 30 NonPresentingGvrDelegate::~NonPresentingGvrDelegate() { |
27 StopVSyncLoop(); | 31 StopVSyncLoop(); |
28 } | 32 } |
29 | 33 |
30 void NonPresentingGvrDelegate::OnVRVsyncProviderRequest( | 34 void NonPresentingGvrDelegate::OnVRVsyncProviderRequest( |
31 device::mojom::VRVSyncProviderRequest request) { | 35 device::mojom::VRVSyncProviderRequest request) { |
32 binding_.Close(); | 36 binding_.Close(); |
33 binding_.Bind(std::move(request)); | 37 binding_.Bind(std::move(request)); |
34 binding_.set_connection_error_handler( | 38 binding_.set_connection_error_handler( |
35 base::Bind(&NonPresentingGvrDelegate::StopVSyncLoop, | 39 base::Bind(&NonPresentingGvrDelegate::StopVSyncLoop, |
36 weak_ptr_factory_.GetWeakPtr())); | 40 weak_ptr_factory_.GetWeakPtr())); |
37 StartVSyncLoop(); | 41 StartVSyncLoop(); |
38 } | 42 } |
39 | 43 |
40 void NonPresentingGvrDelegate::Pause() { | 44 void NonPresentingGvrDelegate::Pause() { |
41 vsync_task_.Cancel(); | 45 vsync_task_.Cancel(); |
42 vsync_paused_ = true; | 46 vsync_paused_ = true; |
43 gvr_api_->PauseTracking(); | 47 if (gvr_api_) |
| 48 gvr_api_->PauseTracking(); |
44 } | 49 } |
45 | 50 |
46 void NonPresentingGvrDelegate::Resume() { | 51 void NonPresentingGvrDelegate::Resume() { |
47 if (!vsync_paused_) | 52 if (!vsync_paused_) |
48 return; | 53 return; |
49 vsync_paused_ = false; | 54 vsync_paused_ = false; |
50 StartVSyncLoop(); | 55 StartVSyncLoop(); |
51 } | 56 } |
52 | 57 |
53 device::mojom::VRVSyncProviderRequest | 58 device::mojom::VRVSyncProviderRequest |
54 NonPresentingGvrDelegate::OnSwitchToPresentingDelegate() { | 59 NonPresentingGvrDelegate::OnSwitchToPresentingDelegate() { |
55 StopVSyncLoop(); | 60 StopVSyncLoop(); |
56 if (binding_.is_bound()) | 61 if (binding_.is_bound()) |
57 return binding_.Unbind(); | 62 return binding_.Unbind(); |
58 return nullptr; | 63 return nullptr; |
59 } | 64 } |
60 | 65 |
61 void NonPresentingGvrDelegate::StopVSyncLoop() { | 66 void NonPresentingGvrDelegate::StopVSyncLoop() { |
62 vsync_task_.Cancel(); | 67 vsync_task_.Cancel(); |
| 68 binding_.Close(); |
63 if (!callback_.is_null()) { | 69 if (!callback_.is_null()) { |
64 base::ResetAndReturn(&callback_) | 70 base::ResetAndReturn(&callback_) |
65 .Run(nullptr, base::TimeDelta(), -1, | 71 .Run(nullptr, base::TimeDelta(), -1, |
66 device::mojom::VRVSyncProvider::Status::RETRY); | 72 device::mojom::VRVSyncProvider::Status::CLOSING); |
67 } | 73 } |
68 gvr_api_->PauseTracking(); | 74 if (gvr_api_) |
| 75 gvr_api_->PauseTracking(); |
69 // If the loop is stopped, it's not considered to be paused. | 76 // If the loop is stopped, it's not considered to be paused. |
70 vsync_paused_ = false; | 77 vsync_paused_ = false; |
71 } | 78 } |
72 | 79 |
73 void NonPresentingGvrDelegate::StartVSyncLoop() { | 80 void NonPresentingGvrDelegate::StartVSyncLoop() { |
74 vsync_task_.Reset( | 81 vsync_task_.Reset( |
75 base::Bind(&NonPresentingGvrDelegate::OnVSync, base::Unretained(this))); | 82 base::Bind(&NonPresentingGvrDelegate::OnVSync, base::Unretained(this))); |
76 gvr_api_->RefreshViewerProfile(); | 83 if (gvr_api_) { |
77 gvr_api_->ResumeTracking(); | 84 gvr_api_->RefreshViewerProfile(); |
| 85 gvr_api_->ResumeTracking(); |
| 86 } |
78 OnVSync(); | 87 OnVSync(); |
79 } | 88 } |
80 | 89 |
81 void NonPresentingGvrDelegate::OnVSync() { | 90 void NonPresentingGvrDelegate::OnVSync() { |
82 base::TimeTicks now = base::TimeTicks::Now(); | 91 base::TimeTicks now = base::TimeTicks::Now(); |
83 base::TimeTicks target; | 92 base::TimeTicks target; |
84 | 93 |
85 // Don't run the VSync loop if we're not bound. | 94 // Don't run the VSync loop if we're not bound. |
86 if (!binding_.is_bound()) { | 95 if (!binding_.is_bound()) { |
87 return; | 96 return; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 vsync_timebase_ += base::TimeDelta::FromMicroseconds(timebase_nanos / 1000); | 138 vsync_timebase_ += base::TimeDelta::FromMicroseconds(timebase_nanos / 1000); |
130 vsync_interval_ = base::TimeDelta::FromSecondsD(interval_seconds); | 139 vsync_interval_ = base::TimeDelta::FromSecondsD(interval_seconds); |
131 StartVSyncLoop(); | 140 StartVSyncLoop(); |
132 } | 141 } |
133 | 142 |
134 void NonPresentingGvrDelegate::SendVSync(base::TimeDelta time, | 143 void NonPresentingGvrDelegate::SendVSync(base::TimeDelta time, |
135 const GetVSyncCallback& callback) { | 144 const GetVSyncCallback& callback) { |
136 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); | 145 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); |
137 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; | 146 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; |
138 | 147 |
| 148 if (!gvr_api_) { |
| 149 callback.Run(device::mojom::VRPosePtr(nullptr), time, -1, |
| 150 device::mojom::VRVSyncProvider::Status::SUCCESS); |
| 151 return; |
| 152 } |
| 153 |
139 gvr::Mat4f head_mat = gvr_api_->ApplyNeckModel( | 154 gvr::Mat4f head_mat = gvr_api_->ApplyNeckModel( |
140 gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time), 1.0f); | 155 gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time), 1.0f); |
141 callback.Run(VrShell::VRPosePtrFromGvrPose(head_mat), time, -1, | 156 callback.Run(VrShell::VRPosePtrFromGvrPose(head_mat), time, -1, |
142 device::mojom::VRVSyncProvider::Status::SUCCESS); | 157 device::mojom::VRVSyncProvider::Status::SUCCESS); |
143 } | 158 } |
144 | 159 |
145 bool NonPresentingGvrDelegate::SupportsPresentation() { | 160 bool NonPresentingGvrDelegate::SupportsPresentation() { |
146 return false; | 161 return false; |
147 } | 162 } |
148 | 163 |
149 void NonPresentingGvrDelegate::ResetPose() { | 164 void NonPresentingGvrDelegate::ResetPose() { |
150 // Should never call RecenterTracking when using with Daydream viewers. On | 165 // Should never call RecenterTracking when using with Daydream viewers. On |
151 // those devices recentering should only be done via the controller. | 166 // those devices recentering should only be done via the controller. |
152 if (gvr_api_ && gvr_api_->GetViewerType() == GVR_VIEWER_TYPE_CARDBOARD) | 167 if (gvr_api_ && gvr_api_->GetViewerType() == GVR_VIEWER_TYPE_CARDBOARD) |
153 gvr_api_->RecenterTracking(); | 168 gvr_api_->RecenterTracking(); |
154 } | 169 } |
155 | 170 |
156 void NonPresentingGvrDelegate::CreateVRDisplayInfo( | 171 void NonPresentingGvrDelegate::CreateVRDisplayInfo( |
157 const base::Callback<void(device::mojom::VRDisplayInfoPtr)>& callback, | 172 const base::Callback<void(device::mojom::VRDisplayInfoPtr)>& callback, |
158 uint32_t device_id) { | 173 uint32_t device_id) { |
159 callback.Run(VrShell::CreateVRDisplayInfo( | 174 if (!gvr_api_) { |
160 gvr_api_.get(), device::kInvalidRenderTargetSize, device_id)); | 175 callback.Run(device::mojom::VRDisplayInfoPtr(nullptr)); |
| 176 return; |
| 177 } |
| 178 |
| 179 gvr::Sizei webvr_size = VrShell::GetRecommendedWebVrSize(gvr_api_.get()); |
| 180 DVLOG(1) << __FUNCTION__ << ": resize recommended to " << webvr_size.width |
| 181 << "x" << webvr_size.height; |
| 182 callback.Run( |
| 183 VrShell::CreateVRDisplayInfo(gvr_api_.get(), webvr_size, device_id)); |
161 } | 184 } |
162 | 185 |
163 } // namespace vr_shell | 186 } // namespace vr_shell |
OLD | NEW |