Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(242)

Side by Side Diff: chrome/browser/android/vr_shell/vr_shell_gl.cc

Issue 2612333002: Allow VRDisplay to specify which frame the layer bounds should be updated at. (Closed)
Patch Set: Address comments Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698