| 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 |