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/vr_shell_gl.h" | 5 #include "chrome/browser/android/vr_shell/vr_shell_gl.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/android/jni_android.h" | 9 #include "base/android/jni_android.h" |
| 10 #include "base/callback_helpers.h" |
10 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
11 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" |
12 #include "base/threading/thread_task_runner_handle.h" | 13 #include "base/threading/thread_task_runner_handle.h" |
13 #include "chrome/browser/android/vr_shell/ui_elements.h" | 14 #include "chrome/browser/android/vr_shell/ui_elements.h" |
14 #include "chrome/browser/android/vr_shell/ui_scene.h" | 15 #include "chrome/browser/android/vr_shell/ui_scene.h" |
15 #include "chrome/browser/android/vr_shell/vr_controller.h" | 16 #include "chrome/browser/android/vr_shell/vr_controller.h" |
16 #include "chrome/browser/android/vr_shell/vr_gl_util.h" | 17 #include "chrome/browser/android/vr_shell/vr_gl_util.h" |
17 #include "chrome/browser/android/vr_shell/vr_math.h" | 18 #include "chrome/browser/android/vr_shell/vr_math.h" |
18 #include "chrome/browser/android/vr_shell/vr_shell.h" | 19 #include "chrome/browser/android/vr_shell/vr_shell.h" |
19 #include "chrome/browser/android/vr_shell/vr_shell_delegate.h" | 20 #include "chrome/browser/android/vr_shell/vr_shell_delegate.h" |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 // is currently sized to fit the WebVR "insecure transport" warnings, | 80 // is currently sized to fit the WebVR "insecure transport" warnings, |
80 // adjust it as needed if there is additional content. | 81 // adjust it as needed if there is additional content. |
81 static constexpr gvr::Sizei kHeadlockedBufferDimensions = {1024, 1024}; | 82 static constexpr gvr::Sizei kHeadlockedBufferDimensions = {1024, 1024}; |
82 static constexpr gvr::Rectf kHeadlockedBufferFov = {20.f, 20.f, 20.f, 20.f}; | 83 static constexpr gvr::Rectf kHeadlockedBufferFov = {20.f, 20.f, 20.f, 20.f}; |
83 | 84 |
84 // The GVR viewport list has two entries (left eye and right eye) for each | 85 // The GVR viewport list has two entries (left eye and right eye) for each |
85 // GVR buffer. | 86 // GVR buffer. |
86 static constexpr int kViewportListPrimaryOffset = 0; | 87 static constexpr int kViewportListPrimaryOffset = 0; |
87 static constexpr int kViewportListHeadlockedOffset = 2; | 88 static constexpr int kViewportListHeadlockedOffset = 2; |
88 | 89 |
| 90 // Buffer size large enough to handle the current backlog of poses which is |
| 91 // 2-3 frames. |
| 92 static constexpr unsigned kPoseRingBufferSize = 8; |
| 93 |
89 // Magic numbers used to mark valid pose index values encoded in frame | 94 // Magic numbers used to mark valid pose index values encoded in frame |
90 // data. Must match the magic numbers used in blink's VRDisplay.cpp. | 95 // data. Must match the magic numbers used in blink's VRDisplay.cpp. |
91 static constexpr std::array<uint8_t, 2> kWebVrPosePixelMagicNumbers{{42, 142}}; | 96 static constexpr std::array<uint8_t, 2> kWebVrPosePixelMagicNumbers{{42, 142}}; |
92 | 97 |
93 float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) { | 98 float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) { |
94 float xdiff = (vec1.x - vec2.x); | 99 float xdiff = (vec1.x - vec2.x); |
95 float ydiff = (vec1.y - vec2.y); | 100 float ydiff = (vec1.y - vec2.y); |
96 float zdiff = (vec1.z - vec2.z); | 101 float zdiff = (vec1.z - vec2.z); |
97 float scale = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff; | 102 float scale = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff; |
98 return std::sqrt(scale); | 103 return std::sqrt(scale); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 binding_(this), | 169 binding_(this), |
165 weak_vr_shell_(weak_vr_shell), | 170 weak_vr_shell_(weak_vr_shell), |
166 delegate_provider_(delegate_provider), | 171 delegate_provider_(delegate_provider), |
167 main_thread_task_runner_(std::move(main_thread_task_runner)), | 172 main_thread_task_runner_(std::move(main_thread_task_runner)), |
168 weak_ptr_factory_(this) { | 173 weak_ptr_factory_(this) { |
169 GvrInit(gvr_api); | 174 GvrInit(gvr_api); |
170 } | 175 } |
171 | 176 |
172 VrShellGl::~VrShellGl() { | 177 VrShellGl::~VrShellGl() { |
173 vsync_task_.Cancel(); | 178 vsync_task_.Cancel(); |
174 if (!callback_.is_null()) | 179 if (!callback_.is_null()) { |
175 callback_.Run(nullptr, base::TimeDelta()); | 180 base::ResetAndReturn(&callback_).Run(nullptr, base::TimeDelta(), -1); |
| 181 } |
176 if (binding_.is_bound()) { | 182 if (binding_.is_bound()) { |
177 main_thread_task_runner_->PostTask(FROM_HERE, base::Bind( | 183 main_thread_task_runner_->PostTask(FROM_HERE, base::Bind( |
178 &VrShellDelegate::OnVRVsyncProviderRequest, delegate_provider_, | 184 &VrShellDelegate::OnVRVsyncProviderRequest, delegate_provider_, |
179 base::Passed(binding_.Unbind()))); | 185 base::Passed(binding_.Unbind()))); |
180 } | 186 } |
181 } | 187 } |
182 | 188 |
183 void VrShellGl::Initialize() { | 189 void VrShellGl::Initialize() { |
184 scene_.reset(new UiScene); | 190 scene_.reset(new UiScene); |
185 | 191 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 | 263 |
258 void VrShellGl::OnUIFrameAvailable() { | 264 void VrShellGl::OnUIFrameAvailable() { |
259 ui_surface_texture_->UpdateTexImage(); | 265 ui_surface_texture_->UpdateTexImage(); |
260 } | 266 } |
261 | 267 |
262 void VrShellGl::OnContentFrameAvailable() { | 268 void VrShellGl::OnContentFrameAvailable() { |
263 content_surface_texture_->UpdateTexImage(); | 269 content_surface_texture_->UpdateTexImage(); |
264 received_frame_ = true; | 270 received_frame_ = true; |
265 } | 271 } |
266 | 272 |
267 bool VrShellGl::GetPixelEncodedPoseIndexByte(int* pose_index) { | 273 bool VrShellGl::GetPixelEncodedFrameIndex(uint16_t* frame_index) { |
268 TRACE_EVENT0("gpu", "VrShellGl::GetPixelEncodedPoseIndex"); | 274 TRACE_EVENT0("gpu", "VrShellGl::GetPixelEncodedFrameIndex"); |
269 if (!received_frame_) { | 275 if (!received_frame_) { |
270 *pose_index = last_pose_; | 276 if (last_frame_index_ == (uint16_t) -1) |
| 277 return false; |
| 278 *frame_index = last_frame_index_; |
271 return true; | 279 return true; |
272 } | 280 } |
273 received_frame_ = false; | 281 received_frame_ = false; |
274 | 282 |
275 // Read the pose index encoded in a bottom left pixel as color values. | 283 // Read the pose index encoded in a bottom left pixel as color values. |
276 // See also third_party/WebKit/Source/modules/vr/VRDisplay.cpp which | 284 // See also third_party/WebKit/Source/modules/vr/VRDisplay.cpp which |
277 // encodes the pose index, and device/vr/android/gvr/gvr_device.cc | 285 // encodes the pose index, and device/vr/android/gvr/gvr_device.cc |
278 // which tracks poses. Returns the low byte (0..255) if valid, or -1 | 286 // which tracks poses. Returns the low byte (0..255) if valid, or -1 |
279 // if not valid due to bad magic number. | 287 // if not valid due to bad magic number. |
280 uint8_t pixels[4]; | 288 uint8_t pixels[4]; |
281 // Assume we're reading from the framebuffer we just wrote to. | 289 // Assume we're reading from the framebuffer we just wrote to. |
282 // That's true currently, we may need to use glReadBuffer(GL_BACK) | 290 // That's true currently, we may need to use glReadBuffer(GL_BACK) |
283 // or equivalent if the rendering setup changes in the future. | 291 // or equivalent if the rendering setup changes in the future. |
284 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels); | 292 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels); |
285 | 293 |
286 // Check for the magic number written by VRDevice.cpp on submit. | 294 // Check for the magic number written by VRDevice.cpp on submit. |
287 // This helps avoid glitches from garbage data in the render | 295 // This helps avoid glitches from garbage data in the render |
288 // buffer that can appear during initialization or resizing. These | 296 // buffer that can appear during initialization or resizing. These |
289 // often appear as flashes of all-black or all-white pixels. | 297 // often appear as flashes of all-black or all-white pixels. |
290 if (pixels[1] == kWebVrPosePixelMagicNumbers[0] && | 298 if (pixels[1] == kWebVrPosePixelMagicNumbers[0] && |
291 pixels[2] == kWebVrPosePixelMagicNumbers[1]) { | 299 pixels[2] == kWebVrPosePixelMagicNumbers[1]) { |
292 // Pose is good. | 300 // Pose is good. |
293 *pose_index = pixels[0]; | 301 *frame_index = pixels[0]; |
294 last_pose_ = pixels[0]; | 302 last_frame_index_ = pixels[0]; |
295 return true; | 303 return true; |
296 } | 304 } |
297 VLOG(1) << "WebVR: reject decoded pose index " << (int)pixels[0] | 305 VLOG(1) << "WebVR: reject decoded pose index " << (int)pixels[0] |
298 << ", bad magic number " << (int)pixels[1] << ", " | 306 << ", bad magic number " << (int)pixels[1] << ", " |
299 << (int)pixels[2]; | 307 << (int)pixels[2]; |
300 return false; | 308 return false; |
301 } | 309 } |
302 | 310 |
303 void VrShellGl::GvrInit(gvr_context* gvr_api) { | 311 void VrShellGl::GvrInit(gvr_context* gvr_api) { |
304 gvr_api_ = gvr::GvrApi::WrapNonOwned(gvr_api); | 312 gvr_api_ = gvr::GvrApi::WrapNonOwned(gvr_api); |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 | 607 |
600 gvr::Frame frame = swap_chain_->AcquireFrame(); | 608 gvr::Frame frame = swap_chain_->AcquireFrame(); |
601 if (!frame.is_valid()) { | 609 if (!frame.is_valid()) { |
602 return; | 610 return; |
603 } | 611 } |
604 frame.BindBuffer(kFramePrimaryBuffer); | 612 frame.BindBuffer(kFramePrimaryBuffer); |
605 if (web_vr_mode_) { | 613 if (web_vr_mode_) { |
606 DrawWebVr(); | 614 DrawWebVr(); |
607 } | 615 } |
608 | 616 |
609 int pose_index; | 617 uint16_t frame_index; |
610 gvr::Mat4f head_pose; | 618 gvr::Mat4f head_pose; |
611 | 619 |
612 // When using async reprojection, we need to know which pose was used in | 620 // When using async reprojection, we need to know which pose was used in |
613 // the WebVR app for drawing this frame. Due to unknown amounts of | 621 // the WebVR app for drawing this frame. Due to unknown amounts of |
614 // buffering in the compositor and SurfaceTexture, we read the pose number | 622 // buffering in the compositor and SurfaceTexture, we read the pose number |
615 // from a corner pixel. There's no point in doing this for legacy | 623 // from a corner pixel. There's no point in doing this for legacy |
616 // distortion rendering since that doesn't need a pose, and reading back | 624 // distortion rendering since that doesn't need a pose, and reading back |
617 // pixels is an expensive operation. TODO(klausw,crbug.com/655722): stop | 625 // pixels is an expensive operation. TODO(klausw,crbug.com/655722): stop |
618 // doing this once we have working no-compositor rendering for WebVR. | 626 // doing this once we have working no-compositor rendering for WebVR. |
619 if (web_vr_mode_ && gvr_api_->GetAsyncReprojectionEnabled() && | 627 if (web_vr_mode_ && gvr_api_->GetAsyncReprojectionEnabled() && |
620 GetPixelEncodedPoseIndexByte(&pose_index)) { | 628 GetPixelEncodedFrameIndex(&frame_index)) { |
621 head_pose = webvr_head_pose_[pose_index % kPoseRingBufferSize]; | 629 static_assert(!((kPoseRingBufferSize - 1) & kPoseRingBufferSize), |
| 630 "kPoseRingBufferSize must be a power of 2"); |
| 631 head_pose = webvr_head_pose_[frame_index % kPoseRingBufferSize]; |
| 632 // Process all pending_bounds_ changes targeted for before this frame, being |
| 633 // careful of wrapping frame indices. |
| 634 static constexpr unsigned max = |
| 635 std::numeric_limits<decltype(frame_index_)>::max(); |
| 636 static_assert(max > kPoseRingBufferSize * 2, |
| 637 "To detect wrapping, kPoseRingBufferSize must be smaller " |
| 638 "than half of frame_index_ range."); |
| 639 while (!pending_bounds_.empty()) { |
| 640 uint16_t index = pending_bounds_.front().first; |
| 641 // If index is less than the frame_index it's possible we've wrapped, so |
| 642 // we extend the range and 'un-wrap' to account for this. |
| 643 if (index < frame_index) index += max; |
| 644 // If the pending bounds change is for an upcoming frame within our buffer |
| 645 // size, wait to apply it. Otherwise, apply it immediately. This |
| 646 // guarantees that even if we miss many frames, the queue can't fill up |
| 647 // with stale bounds. |
| 648 if (index > frame_index && index <= frame_index + kPoseRingBufferSize) |
| 649 break; |
| 650 |
| 651 const BoundsPair& bounds = pending_bounds_.front().second; |
| 652 webvr_left_viewport_->SetSourceUv(bounds.first); |
| 653 webvr_right_viewport_->SetSourceUv(bounds.second); |
| 654 pending_bounds_.pop(); |
| 655 } |
| 656 buffer_viewport_list_->SetBufferViewport(GVR_LEFT_EYE, |
| 657 *webvr_left_viewport_); |
| 658 buffer_viewport_list_->SetBufferViewport(GVR_RIGHT_EYE, |
| 659 *webvr_right_viewport_); |
622 } else { | 660 } else { |
623 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); | 661 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); |
624 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; | 662 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; |
625 head_pose = gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time); | 663 head_pose = gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time); |
626 } | 664 } |
627 | 665 |
628 gvr::Vec3f position = GetTranslation(head_pose); | 666 gvr::Vec3f position = GetTranslation(head_pose); |
629 if (position.x == 0.0f && position.y == 0.0f && position.z == 0.0f) { | 667 if (position.x == 0.0f && position.y == 0.0f && position.z == 0.0f) { |
630 // This appears to be a 3DOF pose without a neck model. Add one. | 668 // This appears to be a 3DOF pose without a neck model. Add one. |
631 // The head pose has redundant data. Assume we're only using the | 669 // The head pose has redundant data. Assume we're only using the |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
858 // Don't need face culling, depth testing, blending, etc. Turn it all off. | 896 // Don't need face culling, depth testing, blending, etc. Turn it all off. |
859 glDisable(GL_CULL_FACE); | 897 glDisable(GL_CULL_FACE); |
860 glDepthMask(GL_FALSE); | 898 glDepthMask(GL_FALSE); |
861 glDisable(GL_DEPTH_TEST); | 899 glDisable(GL_DEPTH_TEST); |
862 glDisable(GL_SCISSOR_TEST); | 900 glDisable(GL_SCISSOR_TEST); |
863 glDisable(GL_BLEND); | 901 glDisable(GL_BLEND); |
864 glDisable(GL_POLYGON_OFFSET_FILL); | 902 glDisable(GL_POLYGON_OFFSET_FILL); |
865 | 903 |
866 glViewport(0, 0, render_size_primary_.width, render_size_primary_.height); | 904 glViewport(0, 0, render_size_primary_.width, render_size_primary_.height); |
867 vr_shell_renderer_->GetWebVrRenderer()->Draw(webvr_texture_id_); | 905 vr_shell_renderer_->GetWebVrRenderer()->Draw(webvr_texture_id_); |
868 | |
869 buffer_viewport_list_->SetBufferViewport(GVR_LEFT_EYE, | |
870 *webvr_left_viewport_); | |
871 buffer_viewport_list_->SetBufferViewport(GVR_RIGHT_EYE, | |
872 *webvr_right_viewport_); | |
873 } | 906 } |
874 | 907 |
875 void VrShellGl::DrawBackground(const gvr::Mat4f& render_matrix) { | 908 void VrShellGl::DrawBackground(const gvr::Mat4f& render_matrix) { |
876 vr_shell_renderer_->GetBackgroundRenderer()->Draw(render_matrix); | 909 vr_shell_renderer_->GetBackgroundRenderer()->Draw(render_matrix); |
877 } | 910 } |
878 | 911 |
879 void VrShellGl::OnTriggerEvent() { | 912 void VrShellGl::OnTriggerEvent() { |
880 // Set a flag to handle this on the render thread at the next frame. | 913 // Set a flag to handle this on the render thread at the next frame. |
881 touch_pending_ = true; | 914 touch_pending_ = true; |
882 } | 915 } |
(...skipping 11 matching lines...) Expand all Loading... |
894 if (ready_to_draw_) { | 927 if (ready_to_draw_) { |
895 vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this))); | 928 vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this))); |
896 OnVSync(); | 929 OnVSync(); |
897 } | 930 } |
898 } | 931 } |
899 | 932 |
900 void VrShellGl::SetWebVrMode(bool enabled) { | 933 void VrShellGl::SetWebVrMode(bool enabled) { |
901 web_vr_mode_ = enabled; | 934 web_vr_mode_ = enabled; |
902 } | 935 } |
903 | 936 |
904 void VrShellGl::UpdateWebVRTextureBounds(const gvr::Rectf& left_bounds, | 937 void VrShellGl::UpdateWebVRTextureBounds(int16_t frame_index, |
| 938 const gvr::Rectf& left_bounds, |
905 const gvr::Rectf& right_bounds) { | 939 const gvr::Rectf& right_bounds) { |
906 webvr_left_viewport_->SetSourceUv(left_bounds); | 940 if (frame_index < 0) { |
907 webvr_right_viewport_->SetSourceUv(right_bounds); | 941 webvr_left_viewport_->SetSourceUv(left_bounds); |
| 942 webvr_right_viewport_->SetSourceUv(right_bounds); |
| 943 } else { |
| 944 pending_bounds_.emplace( |
| 945 std::make_pair(frame_index, std::make_pair(left_bounds, right_bounds))); |
| 946 } |
908 } | 947 } |
909 | 948 |
910 gvr::GvrApi* VrShellGl::gvr_api() { | 949 gvr::GvrApi* VrShellGl::gvr_api() { |
911 return gvr_api_.get(); | 950 return gvr_api_.get(); |
912 } | 951 } |
913 | 952 |
914 void VrShellGl::ContentBoundsChanged(int width, int height) { | 953 void VrShellGl::ContentBoundsChanged(int width, int height) { |
915 TRACE_EVENT0("gpu", "VrShellGl::ContentBoundsChanged"); | 954 TRACE_EVENT0("gpu", "VrShellGl::ContentBoundsChanged"); |
916 content_tex_css_width_ = width; | 955 content_tex_css_width_ = width; |
917 content_tex_css_height_ = height; | 956 content_tex_css_height_ = height; |
(...skipping 30 matching lines...) Expand all Loading... |
948 if (vsync_interval_.is_zero()) | 987 if (vsync_interval_.is_zero()) |
949 return; | 988 return; |
950 target = now + vsync_interval_; | 989 target = now + vsync_interval_; |
951 int64_t intervals = (target - vsync_timebase_) / vsync_interval_; | 990 int64_t intervals = (target - vsync_timebase_) / vsync_interval_; |
952 target = vsync_timebase_ + intervals * vsync_interval_; | 991 target = vsync_timebase_ + intervals * vsync_interval_; |
953 task_runner_->PostDelayedTask(FROM_HERE, vsync_task_.callback(), | 992 task_runner_->PostDelayedTask(FROM_HERE, vsync_task_.callback(), |
954 target - now); | 993 target - now); |
955 | 994 |
956 base::TimeDelta time = intervals * vsync_interval_; | 995 base::TimeDelta time = intervals * vsync_interval_; |
957 if (!callback_.is_null()) { | 996 if (!callback_.is_null()) { |
958 callback_.Run(GetPose(), time); | 997 SendVSync(time, base::ResetAndReturn(&callback_)); |
959 callback_.Reset(); | |
960 } else { | 998 } else { |
961 pending_vsync_ = true; | 999 pending_vsync_ = true; |
962 pending_time_ = time; | 1000 pending_time_ = time; |
963 } | 1001 } |
964 DrawFrame(); | 1002 DrawFrame(); |
965 } | 1003 } |
966 | 1004 |
967 void VrShellGl::OnRequest(device::mojom::VRVSyncProviderRequest request) { | 1005 void VrShellGl::OnRequest(device::mojom::VRVSyncProviderRequest request) { |
968 binding_.Close(); | 1006 binding_.Close(); |
969 binding_.Bind(std::move(request)); | 1007 binding_.Bind(std::move(request)); |
970 } | 1008 } |
971 | 1009 |
972 void VrShellGl::GetVSync(const GetVSyncCallback& callback) { | 1010 void VrShellGl::GetVSync(const GetVSyncCallback& callback) { |
973 if (!pending_vsync_) { | 1011 if (!pending_vsync_) { |
974 if (!callback_.is_null()) { | 1012 if (!callback_.is_null()) { |
975 mojo::ReportBadMessage("Requested VSync before waiting for response to " | 1013 mojo::ReportBadMessage("Requested VSync before waiting for response to " |
976 "previous request."); | 1014 "previous request."); |
977 return; | 1015 return; |
978 } | 1016 } |
979 callback_ = callback; | 1017 callback_ = callback; |
980 return; | 1018 return; |
981 } | 1019 } |
982 pending_vsync_ = false; | 1020 pending_vsync_ = false; |
983 callback.Run(GetPose(), pending_time_); | 1021 SendVSync(pending_time_, callback); |
984 } | 1022 } |
985 | 1023 |
986 void VrShellGl::UpdateVSyncInterval(long timebase_nanos, | 1024 void VrShellGl::UpdateVSyncInterval(long timebase_nanos, |
987 double interval_seconds) { | 1025 double interval_seconds) { |
988 vsync_timebase_ = base::TimeTicks(); | 1026 vsync_timebase_ = base::TimeTicks(); |
989 vsync_timebase_ += base::TimeDelta::FromMicroseconds(timebase_nanos / 1000); | 1027 vsync_timebase_ += base::TimeDelta::FromMicroseconds(timebase_nanos / 1000); |
990 vsync_interval_ = base::TimeDelta::FromSecondsD(interval_seconds); | 1028 vsync_interval_ = base::TimeDelta::FromSecondsD(interval_seconds); |
991 vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this))); | 1029 vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this))); |
992 OnVSync(); | 1030 OnVSync(); |
993 } | 1031 } |
994 | 1032 |
995 void VrShellGl::ForceExitVr() { | 1033 void VrShellGl::ForceExitVr() { |
996 main_thread_task_runner_->PostTask( | 1034 main_thread_task_runner_->PostTask( |
997 FROM_HERE, base::Bind(&VrShell::ForceExitVr, weak_vr_shell_)); | 1035 FROM_HERE, base::Bind(&VrShell::ForceExitVr, weak_vr_shell_)); |
998 } | 1036 } |
999 | 1037 |
1000 void VrShellGl::UpdateScene(std::unique_ptr<base::ListValue> commands) { | 1038 void VrShellGl::UpdateScene(std::unique_ptr<base::ListValue> commands) { |
1001 scene_->HandleCommands(std::move(commands), TimeInMicroseconds()); | 1039 scene_->HandleCommands(std::move(commands), TimeInMicroseconds()); |
1002 } | 1040 } |
1003 | 1041 |
1004 device::mojom::VRPosePtr VrShellGl::GetPose() { | 1042 void VrShellGl::SendVSync(base::TimeDelta time, |
1005 TRACE_EVENT0("input", "VrShellGl::GetPose"); | 1043 const GetVSyncCallback& callback) { |
| 1044 TRACE_EVENT0("input", "VrShellGl::SendVSync"); |
| 1045 |
| 1046 uint8_t frame_index = frame_index_++; |
1006 | 1047 |
1007 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); | 1048 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); |
1008 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; | 1049 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; |
1009 | 1050 |
1010 gvr::Mat4f head_mat = | 1051 gvr::Mat4f head_mat = |
1011 gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time); | 1052 gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time); |
1012 head_mat = gvr_api_->ApplyNeckModel(head_mat, 1.0f); | 1053 head_mat = gvr_api_->ApplyNeckModel(head_mat, 1.0f); |
1013 | 1054 |
1014 uint32_t pose_index = pose_index_++; | 1055 webvr_head_pose_[frame_index % kPoseRingBufferSize] = head_mat; |
1015 webvr_head_pose_[pose_index % kPoseRingBufferSize] = head_mat; | |
1016 | 1056 |
1017 return VrShell::VRPosePtrFromGvrPose(head_mat, pose_index); | 1057 callback.Run(VrShell::VRPosePtrFromGvrPose(head_mat), time, frame_index); |
1018 } | 1058 } |
1019 | 1059 |
1020 } // namespace vr_shell | 1060 } // namespace vr_shell |
OLD | NEW |