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