Chromium Code Reviews| 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 |