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 if (context) |
dcheng
2017/03/08 07:23:39
Just for my understanding: why can context be null
klausw
2017/03/08 08:11:09
mthiesse@, can you clarify? You had suggested this
mthiesse
2017/03/08 13:44:48
Yeah, this is to prevent crashes in strange error
klausw
2017/03/08 16:56:26
Added this as a comment. That is rather devious.
| |
24 gvr_api_ = gvr::GvrApi::WrapNonOwned(context); | |
24 } | 25 } |
25 | 26 |
26 NonPresentingGvrDelegate::~NonPresentingGvrDelegate() { | 27 NonPresentingGvrDelegate::~NonPresentingGvrDelegate() { |
27 StopVSyncLoop(); | 28 StopVSyncLoop(); |
28 } | 29 } |
29 | 30 |
30 void NonPresentingGvrDelegate::OnVRVsyncProviderRequest( | 31 void NonPresentingGvrDelegate::OnVRVsyncProviderRequest( |
31 device::mojom::VRVSyncProviderRequest request) { | 32 device::mojom::VRVSyncProviderRequest request) { |
32 binding_.Close(); | 33 binding_.Close(); |
33 binding_.Bind(std::move(request)); | 34 binding_.Bind(std::move(request)); |
34 binding_.set_connection_error_handler( | 35 binding_.set_connection_error_handler( |
35 base::Bind(&NonPresentingGvrDelegate::StopVSyncLoop, | 36 base::Bind(&NonPresentingGvrDelegate::StopVSyncLoop, |
36 weak_ptr_factory_.GetWeakPtr())); | 37 weak_ptr_factory_.GetWeakPtr())); |
37 StartVSyncLoop(); | 38 StartVSyncLoop(); |
38 } | 39 } |
39 | 40 |
40 void NonPresentingGvrDelegate::Pause() { | 41 void NonPresentingGvrDelegate::Pause() { |
41 vsync_task_.Cancel(); | 42 vsync_task_.Cancel(); |
42 vsync_paused_ = true; | 43 vsync_paused_ = true; |
43 gvr_api_->PauseTracking(); | 44 if (gvr_api_) |
45 gvr_api_->PauseTracking(); | |
44 } | 46 } |
45 | 47 |
46 void NonPresentingGvrDelegate::Resume() { | 48 void NonPresentingGvrDelegate::Resume() { |
47 if (!vsync_paused_) | 49 if (!vsync_paused_) |
48 return; | 50 return; |
49 vsync_paused_ = false; | 51 vsync_paused_ = false; |
50 StartVSyncLoop(); | 52 StartVSyncLoop(); |
51 } | 53 } |
52 | 54 |
53 device::mojom::VRVSyncProviderRequest | 55 device::mojom::VRVSyncProviderRequest |
54 NonPresentingGvrDelegate::OnSwitchToPresentingDelegate() { | 56 NonPresentingGvrDelegate::OnSwitchToPresentingDelegate() { |
55 StopVSyncLoop(); | 57 StopVSyncLoop(); |
56 if (binding_.is_bound()) | 58 if (binding_.is_bound()) |
57 return binding_.Unbind(); | 59 return binding_.Unbind(); |
58 return nullptr; | 60 return nullptr; |
59 } | 61 } |
60 | 62 |
61 void NonPresentingGvrDelegate::StopVSyncLoop() { | 63 void NonPresentingGvrDelegate::StopVSyncLoop() { |
62 vsync_task_.Cancel(); | 64 vsync_task_.Cancel(); |
65 binding_.Close(); | |
63 if (!callback_.is_null()) { | 66 if (!callback_.is_null()) { |
64 base::ResetAndReturn(&callback_) | 67 base::ResetAndReturn(&callback_) |
65 .Run(nullptr, base::TimeDelta(), -1, | 68 .Run(nullptr, base::TimeDelta(), -1, |
66 device::mojom::VRVSyncProvider::Status::RETRY); | 69 device::mojom::VRVSyncProvider::Status::CLOSING); |
67 } | 70 } |
68 gvr_api_->PauseTracking(); | 71 if (gvr_api_) |
72 gvr_api_->PauseTracking(); | |
69 // If the loop is stopped, it's not considered to be paused. | 73 // If the loop is stopped, it's not considered to be paused. |
70 vsync_paused_ = false; | 74 vsync_paused_ = false; |
71 } | 75 } |
72 | 76 |
73 void NonPresentingGvrDelegate::StartVSyncLoop() { | 77 void NonPresentingGvrDelegate::StartVSyncLoop() { |
74 vsync_task_.Reset( | 78 vsync_task_.Reset( |
75 base::Bind(&NonPresentingGvrDelegate::OnVSync, base::Unretained(this))); | 79 base::Bind(&NonPresentingGvrDelegate::OnVSync, base::Unretained(this))); |
76 gvr_api_->RefreshViewerProfile(); | 80 if (gvr_api_) { |
77 gvr_api_->ResumeTracking(); | 81 gvr_api_->RefreshViewerProfile(); |
82 gvr_api_->ResumeTracking(); | |
83 } | |
78 OnVSync(); | 84 OnVSync(); |
79 } | 85 } |
80 | 86 |
81 void NonPresentingGvrDelegate::OnVSync() { | 87 void NonPresentingGvrDelegate::OnVSync() { |
82 base::TimeTicks now = base::TimeTicks::Now(); | 88 base::TimeTicks now = base::TimeTicks::Now(); |
83 base::TimeTicks target; | 89 base::TimeTicks target; |
84 | 90 |
85 // Don't run the VSync loop if we're not bound. | 91 // Don't run the VSync loop if we're not bound. |
86 if (!binding_.is_bound()) { | 92 if (!binding_.is_bound()) { |
87 return; | 93 return; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
129 vsync_timebase_ += base::TimeDelta::FromMicroseconds(timebase_nanos / 1000); | 135 vsync_timebase_ += base::TimeDelta::FromMicroseconds(timebase_nanos / 1000); |
130 vsync_interval_ = base::TimeDelta::FromSecondsD(interval_seconds); | 136 vsync_interval_ = base::TimeDelta::FromSecondsD(interval_seconds); |
131 StartVSyncLoop(); | 137 StartVSyncLoop(); |
132 } | 138 } |
133 | 139 |
134 void NonPresentingGvrDelegate::SendVSync(base::TimeDelta time, | 140 void NonPresentingGvrDelegate::SendVSync(base::TimeDelta time, |
135 const GetVSyncCallback& callback) { | 141 const GetVSyncCallback& callback) { |
136 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); | 142 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); |
137 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; | 143 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; |
138 | 144 |
145 if (!gvr_api_) { | |
146 callback.Run(device::mojom::VRPosePtr(nullptr), time, -1, | |
147 device::mojom::VRVSyncProvider::Status::SUCCESS); | |
148 return; | |
149 } | |
150 | |
139 gvr::Mat4f head_mat = gvr_api_->ApplyNeckModel( | 151 gvr::Mat4f head_mat = gvr_api_->ApplyNeckModel( |
140 gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time), 1.0f); | 152 gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time), 1.0f); |
141 callback.Run(VrShell::VRPosePtrFromGvrPose(head_mat), time, -1, | 153 callback.Run(VrShell::VRPosePtrFromGvrPose(head_mat), time, -1, |
142 device::mojom::VRVSyncProvider::Status::SUCCESS); | 154 device::mojom::VRVSyncProvider::Status::SUCCESS); |
143 } | 155 } |
144 | 156 |
145 bool NonPresentingGvrDelegate::SupportsPresentation() { | 157 bool NonPresentingGvrDelegate::SupportsPresentation() { |
146 return false; | 158 return false; |
147 } | 159 } |
148 | 160 |
149 void NonPresentingGvrDelegate::ResetPose() { | 161 void NonPresentingGvrDelegate::ResetPose() { |
150 // Should never call RecenterTracking when using with Daydream viewers. On | 162 // Should never call RecenterTracking when using with Daydream viewers. On |
151 // those devices recentering should only be done via the controller. | 163 // those devices recentering should only be done via the controller. |
152 if (gvr_api_ && gvr_api_->GetViewerType() == GVR_VIEWER_TYPE_CARDBOARD) | 164 if (gvr_api_ && gvr_api_->GetViewerType() == GVR_VIEWER_TYPE_CARDBOARD) |
153 gvr_api_->RecenterTracking(); | 165 gvr_api_->RecenterTracking(); |
154 } | 166 } |
155 | 167 |
156 void NonPresentingGvrDelegate::CreateVRDisplayInfo( | 168 void NonPresentingGvrDelegate::CreateVRDisplayInfo( |
157 const base::Callback<void(device::mojom::VRDisplayInfoPtr)>& callback, | 169 const base::Callback<void(device::mojom::VRDisplayInfoPtr)>& callback, |
158 uint32_t device_id) { | 170 uint32_t device_id) { |
171 if (!gvr_api_) { | |
172 callback.Run(device::mojom::VRDisplayInfoPtr(nullptr)); | |
173 return; | |
174 } | |
175 | |
159 callback.Run(VrShell::CreateVRDisplayInfo( | 176 callback.Run(VrShell::CreateVRDisplayInfo( |
160 gvr_api_.get(), device::kInvalidRenderTargetSize, device_id)); | 177 gvr_api_.get(), device::kInvalidRenderTargetSize, device_id)); |
161 } | 178 } |
162 | 179 |
163 } // namespace vr_shell | 180 } // namespace vr_shell |
OLD | NEW |