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

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

Issue 2624633002: Remove Sync GetPose VRService call, implement VRVSyncProvider (Closed)
Patch Set: 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 "base/android/jni_android.h" 7 #include "base/android/jni_android.h"
8 #include "base/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
9 #include "base/metrics/histogram_macros.h" 9 #include "base/metrics/histogram_macros.h"
10 #include "base/threading/thread_task_runner_handle.h" 10 #include "base/threading/thread_task_runner_handle.h"
11 #include "chrome/browser/android/vr_shell/ui_elements.h" 11 #include "chrome/browser/android/vr_shell/ui_elements.h"
12 #include "chrome/browser/android/vr_shell/ui_scene.h" 12 #include "chrome/browser/android/vr_shell/ui_scene.h"
13 #include "chrome/browser/android/vr_shell/vr_controller.h" 13 #include "chrome/browser/android/vr_shell/vr_controller.h"
14 #include "chrome/browser/android/vr_shell/vr_gl_util.h" 14 #include "chrome/browser/android/vr_shell/vr_gl_util.h"
15 #include "chrome/browser/android/vr_shell/vr_input_manager.h" 15 #include "chrome/browser/android/vr_shell/vr_input_manager.h"
16 #include "chrome/browser/android/vr_shell/vr_math.h" 16 #include "chrome/browser/android/vr_shell/vr_math.h"
17 #include "chrome/browser/android/vr_shell/vr_shell.h" 17 #include "chrome/browser/android/vr_shell/vr_shell.h"
18 #include "chrome/browser/android/vr_shell/vr_shell_renderer.h" 18 #include "chrome/browser/android/vr_shell/vr_shell_renderer.h"
19 #include "third_party/WebKit/public/platform/WebInputEvent.h" 19 #include "third_party/WebKit/public/platform/WebInputEvent.h"
20 #include "ui/gfx/transform.h"
21 #include "ui/gfx/transform_util.h"
20 #include "ui/gfx/vsync_provider.h" 22 #include "ui/gfx/vsync_provider.h"
21 #include "ui/gl/android/scoped_java_surface.h" 23 #include "ui/gl/android/scoped_java_surface.h"
22 #include "ui/gl/android/surface_texture.h" 24 #include "ui/gl/android/surface_texture.h"
23 #include "ui/gl/gl_bindings.h" 25 #include "ui/gl/gl_bindings.h"
24 #include "ui/gl/gl_context.h" 26 #include "ui/gl/gl_context.h"
25 #include "ui/gl/gl_surface.h" 27 #include "ui/gl/gl_surface.h"
26 #include "ui/gl/init/gl_factory.h" 28 #include "ui/gl/init/gl_factory.h"
27 29
28 namespace vr_shell { 30 namespace vr_shell {
29 31
30 namespace { 32 namespace {
31 // Constant taken from treasure_hunt demo. 33 // TODO(mthiesse): If gvr::PlatformInfo().GetPosePredictionTime() is ever
34 // exposed, use that instead (it defaults to 50ms on most platforms).
32 static constexpr long kPredictionTimeWithoutVsyncNanos = 50000000; 35 static constexpr long kPredictionTimeWithoutVsyncNanos = 50000000;
33 36
34 static constexpr float kZNear = 0.1f; 37 static constexpr float kZNear = 0.1f;
35 static constexpr float kZFar = 1000.0f; 38 static constexpr float kZFar = 1000.0f;
36 39
37 // Screen angle in degrees. 0 = vertical, positive = top closer. 40 // Screen angle in degrees. 0 = vertical, positive = top closer.
38 static constexpr float kDesktopScreenTiltDefault = 0; 41 static constexpr float kDesktopScreenTiltDefault = 0;
39 42
40 static constexpr float kReticleWidth = 0.025f; 43 static constexpr float kReticleWidth = 0.025f;
41 static constexpr float kReticleHeight = 0.025f; 44 static constexpr float kReticleHeight = 0.025f;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 return mouse_event; 138 return mouse_event;
136 } 139 }
137 140
138 enum class ViewerType { 141 enum class ViewerType {
139 UNKNOWN_TYPE = 0, 142 UNKNOWN_TYPE = 0,
140 CARDBOARD = 1, 143 CARDBOARD = 1,
141 DAYDREAM = 2, 144 DAYDREAM = 2,
142 VIEWER_TYPE_MAX, 145 VIEWER_TYPE_MAX,
143 }; 146 };
144 147
145 int GetPixelEncodedPoseIndexByte() { 148 bool GetPixelEncodedPoseIndexByte(int* pose_index) {
146 TRACE_EVENT0("gpu", "VrShellGl::GetPixelEncodedPoseIndex"); 149 TRACE_EVENT0("gpu", "VrShellGl::GetPixelEncodedPoseIndex");
147 // Read the pose index encoded in a bottom left pixel as color values. 150 // Read the pose index encoded in a bottom left pixel as color values.
148 // See also third_party/WebKit/Source/modules/vr/VRDisplay.cpp which 151 // See also third_party/WebKit/Source/modules/vr/VRDisplay.cpp which
149 // encodes the pose index, and device/vr/android/gvr/gvr_device.cc 152 // encodes the pose index, and device/vr/android/gvr/gvr_device.cc
150 // which tracks poses. Returns the low byte (0..255) if valid, or -1 153 // which tracks poses. Returns the low byte (0..255) if valid, or -1
151 // if not valid due to bad magic number. 154 // if not valid due to bad magic number.
152 uint8_t pixels[4]; 155 uint8_t pixels[4];
153 // Assume we're reading from the framebuffer we just wrote to. 156 // Assume we're reading from the framebuffer we just wrote to.
154 // That's true currently, we may need to use glReadBuffer(GL_BACK) 157 // That's true currently, we may need to use glReadBuffer(GL_BACK)
155 // or equivalent if the rendering setup changes in the future. 158 // or equivalent if the rendering setup changes in the future.
156 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 159 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
157 160
158 // Check for the magic number written by VRDevice.cpp on submit. 161 // Check for the magic number written by VRDevice.cpp on submit.
159 // This helps avoid glitches from garbage data in the render 162 // This helps avoid glitches from garbage data in the render
160 // buffer that can appear during initialization or resizing. These 163 // buffer that can appear during initialization or resizing. These
161 // often appear as flashes of all-black or all-white pixels. 164 // often appear as flashes of all-black or all-white pixels.
162 if (pixels[1] == kWebVrPosePixelMagicNumbers[0] && 165 if (pixels[1] == kWebVrPosePixelMagicNumbers[0] &&
163 pixels[2] == kWebVrPosePixelMagicNumbers[1]) { 166 pixels[2] == kWebVrPosePixelMagicNumbers[1]) {
164 // Pose is good. 167 // Pose is good.
165 return pixels[0]; 168 *pose_index = pixels[0];
169 return true;
166 } 170 }
167 VLOG(1) << "WebVR: reject decoded pose index " << (int)pixels[0] << 171 VLOG(1) << "WebVR: reject decoded pose index " << (int)pixels[0]
168 ", bad magic number " << (int)pixels[1] << ", " << (int)pixels[2]; 172 << ", bad magic number " << (int)pixels[1] << ", "
169 return -1; 173 << (int)pixels[2];
174 return false;
170 } 175 }
171 176
172 int64_t TimeInMicroseconds() { 177 int64_t TimeInMicroseconds() {
173 return std::chrono::duration_cast<std::chrono::microseconds>( 178 return std::chrono::duration_cast<std::chrono::microseconds>(
174 std::chrono::steady_clock::now().time_since_epoch()).count(); 179 std::chrono::steady_clock::now().time_since_epoch()).count();
175 } 180 }
176 181
177 void WaitForSwapAck(const base::Closure& callback, gfx::SwapResult result) { 182 void WaitForSwapAck(const base::Closure& callback, gfx::SwapResult result) {
178 callback.Run(); 183 callback.Run();
179 } 184 }
(...skipping 17 matching lines...) Expand all
197 main_thread_task_runner_(std::move(main_thread_task_runner)), 202 main_thread_task_runner_(std::move(main_thread_task_runner)),
198 weak_ptr_factory_(this) { 203 weak_ptr_factory_(this) {
199 GvrInit(gvr_api); 204 GvrInit(gvr_api);
200 } 205 }
201 206
202 VrShellGl::~VrShellGl() { 207 VrShellGl::~VrShellGl() {
203 draw_task_.Cancel(); 208 draw_task_.Cancel();
204 } 209 }
205 210
206 void VrShellGl::Initialize() { 211 void VrShellGl::Initialize() {
207 gvr::Mat4f identity;
208 SetIdentityM(identity);
209 webvr_head_pose_.resize(kPoseRingBufferSize, identity);
210 webvr_head_pose_valid_.resize(kPoseRingBufferSize, false);
211
212 scene_.reset(new UiScene); 212 scene_.reset(new UiScene);
213 213
214 if (surfaceless_rendering_) { 214 if (surfaceless_rendering_) {
215 // If we're rendering surfaceless, we'll never get a java surface to render 215 // If we're rendering surfaceless, we'll never get a java surface to render
216 // into, so we can initialize GL right away. 216 // into, so we can initialize GL right away.
217 InitializeGl(nullptr); 217 InitializeGl(nullptr);
218 } 218 }
219 } 219 }
220 220
221 void VrShellGl::InitializeGl(gfx::AcceleratedWidget window) { 221 void VrShellGl::InitializeGl(gfx::AcceleratedWidget window) {
(...skipping 22 matching lines...) Expand all
244 LOG(ERROR) << "gl::init::CreateGLContext failed"; 244 LOG(ERROR) << "gl::init::CreateGLContext failed";
245 ForceExitVr(); 245 ForceExitVr();
246 return; 246 return;
247 } 247 }
248 if (!context_->MakeCurrent(surface_.get())) { 248 if (!context_->MakeCurrent(surface_.get())) {
249 LOG(ERROR) << "gl::GLContext::MakeCurrent() failed"; 249 LOG(ERROR) << "gl::GLContext::MakeCurrent() failed";
250 ForceExitVr(); 250 ForceExitVr();
251 return; 251 return;
252 } 252 }
253 253
254 // TODO(mthiesse): We don't appear to have a VSync provider ever here. This is
255 // sort of okay, because the GVR swap chain will block if we render too fast,
256 // but we should address this properly.
257 if (surface_->GetVSyncProvider()) {
258 surface_->GetVSyncProvider()->GetVSyncParameters(base::Bind(
259 &VrShellGl::UpdateVSyncParameters, weak_ptr_factory_.GetWeakPtr()));
260 } else {
261 LOG(ERROR) << "No VSync Provider";
262 }
263
264 unsigned int textures[2]; 254 unsigned int textures[2];
265 glGenTextures(2, textures); 255 glGenTextures(2, textures);
266 ui_texture_id_ = textures[0]; 256 ui_texture_id_ = textures[0];
267 content_texture_id_ = textures[1]; 257 content_texture_id_ = textures[1];
268 ui_surface_texture_ = gl::SurfaceTexture::Create(ui_texture_id_); 258 ui_surface_texture_ = gl::SurfaceTexture::Create(ui_texture_id_);
269 content_surface_texture_ = gl::SurfaceTexture::Create(content_texture_id_); 259 content_surface_texture_ = gl::SurfaceTexture::Create(content_texture_id_);
270 ui_surface_.reset(new gl::ScopedJavaSurface(ui_surface_texture_.get())); 260 ui_surface_.reset(new gl::ScopedJavaSurface(ui_surface_texture_.get()));
271 content_surface_.reset(new gl::ScopedJavaSurface( 261 content_surface_.reset(new gl::ScopedJavaSurface(
272 content_surface_texture_.get())); 262 content_surface_texture_.get()));
273 ui_surface_texture_->SetFrameAvailableCallback(base::Bind( 263 ui_surface_texture_->SetFrameAvailableCallback(base::Bind(
274 &VrShellGl::OnUIFrameAvailable, weak_ptr_factory_.GetWeakPtr())); 264 &VrShellGl::OnUIFrameAvailable, weak_ptr_factory_.GetWeakPtr()));
275 content_surface_texture_->SetFrameAvailableCallback(base::Bind( 265 content_surface_texture_->SetFrameAvailableCallback(base::Bind(
276 &VrShellGl::OnContentFrameAvailable, weak_ptr_factory_.GetWeakPtr())); 266 &VrShellGl::OnContentFrameAvailable, weak_ptr_factory_.GetWeakPtr()));
277 267
278 content_surface_texture_->SetDefaultBufferSize( 268 content_surface_texture_->SetDefaultBufferSize(
279 content_tex_physical_size_.width, content_tex_physical_size_.height); 269 content_tex_physical_size_.width, content_tex_physical_size_.height);
280 ui_surface_texture_->SetDefaultBufferSize(ui_tex_physical_size_.width, 270 ui_surface_texture_->SetDefaultBufferSize(ui_tex_physical_size_.width,
281 ui_tex_physical_size_.height); 271 ui_tex_physical_size_.height);
282 272
283 main_thread_task_runner_->PostTask(FROM_HERE, base::Bind( 273 main_thread_task_runner_->PostTask(FROM_HERE, base::Bind(
284 &VrShell::SurfacesChanged, weak_vr_shell_, 274 &VrShell::SurfacesChanged, weak_vr_shell_,
285 content_surface_->j_surface().obj(), 275 content_surface_->j_surface().obj(),
286 ui_surface_->j_surface().obj())); 276 ui_surface_->j_surface().obj()));
287 277
288 InitializeRenderer(); 278 InitializeRenderer();
289 279
290 draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this))); 280 draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this)));
291 ScheduleNextDrawFrame(); 281 ScheduleNextDrawFrame();
292 282
283 main_thread_task_runner_->PostTask(FROM_HERE, base::Bind(
284 &VrShell::OnVRVsyncProviderReady, weak_vr_shell_));
285
293 ready_to_draw_ = true; 286 ready_to_draw_ = true;
294 } 287 }
295 288
296 void VrShellGl::OnUIFrameAvailable() { 289 void VrShellGl::OnUIFrameAvailable() {
297 ui_surface_texture_->UpdateTexImage(); 290 ui_surface_texture_->UpdateTexImage();
298 } 291 }
299 292
300 void VrShellGl::OnContentFrameAvailable() { 293 void VrShellGl::OnContentFrameAvailable() {
301 content_surface_texture_->UpdateTexImage(); 294 content_surface_texture_->UpdateTexImage();
302 } 295 }
(...skipping 18 matching lines...) Expand all
321 UMA_HISTOGRAM_ENUMERATION("VRViewerType", static_cast<int>(viewerType), 314 UMA_HISTOGRAM_ENUMERATION("VRViewerType", static_cast<int>(viewerType),
322 static_cast<int>(ViewerType::VIEWER_TYPE_MAX)); 315 static_cast<int>(ViewerType::VIEWER_TYPE_MAX));
323 } 316 }
324 317
325 void VrShellGl::InitializeRenderer() { 318 void VrShellGl::InitializeRenderer() {
326 // While WebVR is going through the compositor path, it shares 319 // While WebVR is going through the compositor path, it shares
327 // the same texture ID. This will change once it gets its own 320 // the same texture ID. This will change once it gets its own
328 // surface, but store it separately to avoid future confusion. 321 // surface, but store it separately to avoid future confusion.
329 // TODO(klausw,crbug.com/655722): remove this. 322 // TODO(klausw,crbug.com/655722): remove this.
330 webvr_texture_id_ = content_texture_id_; 323 webvr_texture_id_ = content_texture_id_;
331 // Out of paranoia, explicitly reset the "pose valid" flags to false
332 // from the GL thread. The constructor ran in the UI thread.
333 // TODO(klausw,crbug.com/655722): remove this.
334 webvr_head_pose_valid_.assign(kPoseRingBufferSize, false);
335 324
336 gvr_api_->InitializeGl(); 325 gvr_api_->InitializeGl();
326 webvr_head_pose_.assign(kPoseRingBufferSize,
327 gvr_api_->GetHeadSpaceFromStartSpaceRotation(
328 gvr::GvrApi::GetTimePointNow()));
329
337 std::vector<gvr::BufferSpec> specs; 330 std::vector<gvr::BufferSpec> specs;
338 // For kFramePrimaryBuffer (primary VrShell and WebVR content) 331 // For kFramePrimaryBuffer (primary VrShell and WebVR content)
339 specs.push_back(gvr_api_->CreateBufferSpec()); 332 specs.push_back(gvr_api_->CreateBufferSpec());
340 render_size_primary_ = specs[kFramePrimaryBuffer].GetSize(); 333 render_size_primary_ = specs[kFramePrimaryBuffer].GetSize();
341 334
342 // For kFrameHeadlockedBuffer (for WebVR insecure content warning). 335 // For kFrameHeadlockedBuffer (for WebVR insecure content warning).
343 // Set this up at fixed resolution, the (smaller) FOV gets set below. 336 // Set this up at fixed resolution, the (smaller) FOV gets set below.
344 specs.push_back(gvr_api_->CreateBufferSpec()); 337 specs.push_back(gvr_api_->CreateBufferSpec());
345 specs.back().SetSize(kHeadlockedBufferDimensions); 338 specs.back().SetSize(kHeadlockedBufferDimensions);
346 render_size_headlocked_ = specs[kFrameHeadlockedBuffer].GetSize(); 339 render_size_headlocked_ = specs[kFrameHeadlockedBuffer].GetSize();
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 DCHECK(input_target != InputTarget::NONE); 579 DCHECK(input_target != InputTarget::NONE);
587 const base::WeakPtr<VrInputManager>& weak_ptr = 580 const base::WeakPtr<VrInputManager>& weak_ptr =
588 input_target == InputTarget::CONTENT ? content_input_manager_ 581 input_target == InputTarget::CONTENT ? content_input_manager_
589 : ui_input_manager_; 582 : ui_input_manager_;
590 main_thread_task_runner_->PostTask( 583 main_thread_task_runner_->PostTask(
591 FROM_HERE, 584 FROM_HERE,
592 base::Bind(&VrInputManager::ProcessUpdatedGesture, weak_ptr, 585 base::Bind(&VrInputManager::ProcessUpdatedGesture, weak_ptr,
593 base::Passed(std::move(event)))); 586 base::Passed(std::move(event))));
594 } 587 }
595 588
596 void VrShellGl::SetGvrPoseForWebVr(const gvr::Mat4f& pose, uint32_t pose_num) {
597 webvr_head_pose_[pose_num % kPoseRingBufferSize] = pose;
598 webvr_head_pose_valid_[pose_num % kPoseRingBufferSize] = true;
599 }
600
601 bool VrShellGl::WebVrPoseByteIsValid(int pose_index_byte) {
602 if (pose_index_byte < 0) {
603 return false;
604 }
605 if (!webvr_head_pose_valid_[pose_index_byte % kPoseRingBufferSize]) {
606 VLOG(1) << "WebVR: reject decoded pose index " << pose_index_byte <<
607 ", not a valid pose";
608 return false;
609 }
610 return true;
611 }
612
613 void VrShellGl::DrawFrame() { 589 void VrShellGl::DrawFrame() {
614 TRACE_EVENT0("gpu", "VrShellGl::DrawFrame"); 590 TRACE_EVENT0("gpu", "VrShellGl::DrawFrame");
591
615 // Reset the viewport list to just the pair of viewports for the 592 // Reset the viewport list to just the pair of viewports for the
616 // primary buffer each frame. Head-locked viewports get added by 593 // primary buffer each frame. Head-locked viewports get added by
617 // DrawVrShell if needed. 594 // DrawVrShell if needed.
618 buffer_viewport_list_->SetToRecommendedBufferViewports(); 595 buffer_viewport_list_->SetToRecommendedBufferViewports();
619 596
620 gvr::Frame frame = swap_chain_->AcquireFrame(); 597 gvr::Frame frame = swap_chain_->AcquireFrame();
621 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow();
622 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos;
623 598
624 gvr::Mat4f head_pose = 599 frame.BindBuffer(kFramePrimaryBuffer);
625 gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time); 600 if (web_vr_mode_) {
601 DrawWebVr();
602 }
603
604 int pose_index;
605 gvr::Mat4f head_pose;
606
607 // When using async reprojection, we need to know which pose was used in
608 // the WebVR app for drawing this frame. Due to unknown amounts of
609 // buffering in the compositor and SurfaceTexture, we read the pose number
610 // from a corner pixel. There's no point in doing this for legacy
611 // distortion rendering since that doesn't need a pose, and reading back
612 // pixels is an expensive operation. TODO(klausw,crbug.com/655722): stop
613 // doing this once we have working no-compositor rendering for WebVR.
614 if (web_vr_mode_ && gvr_api_->GetAsyncReprojectionEnabled() &&
615 GetPixelEncodedPoseIndexByte(&pose_index)) {
616 head_pose = webvr_head_pose_[pose_index % kPoseRingBufferSize];
617 } else {
618 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow();
619 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos;
620 head_pose = gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time);
621 }
626 622
627 gvr::Vec3f position = GetTranslation(head_pose); 623 gvr::Vec3f position = GetTranslation(head_pose);
628 if (position.x == 0.0f && position.y == 0.0f && position.z == 0.0f) { 624 if (position.x == 0.0f && position.y == 0.0f && position.z == 0.0f) {
629 // This appears to be a 3DOF pose without a neck model. Add one. 625 // This appears to be a 3DOF pose without a neck model. Add one.
630 // The head pose has redundant data. Assume we're only using the 626 // The head pose has redundant data. Assume we're only using the
631 // object_from_reference_matrix, we're not updating position_external. 627 // object_from_reference_matrix, we're not updating position_external.
632 // TODO: Not sure what object_from_reference_matrix is. The new api removed 628 // TODO: Not sure what object_from_reference_matrix is. The new api removed
633 // it. For now, removing it seems working fine. 629 // it. For now, removing it seems working fine.
634 gvr_api_->ApplyNeckModel(head_pose, 1.0f); 630 gvr_api_->ApplyNeckModel(head_pose, 1.0f);
635 } 631 }
636 632
637 frame.BindBuffer(kFramePrimaryBuffer);
638
639 // Update the render position of all UI elements (including desktop). 633 // Update the render position of all UI elements (including desktop).
640 const float screen_tilt = kDesktopScreenTiltDefault * M_PI / 180.0f; 634 const float screen_tilt = kDesktopScreenTiltDefault * M_PI / 180.0f;
641 scene_->UpdateTransforms(screen_tilt, TimeInMicroseconds()); 635 scene_->UpdateTransforms(screen_tilt, TimeInMicroseconds());
642 636
643 UpdateController(GetForwardVector(head_pose)); 637 UpdateController(GetForwardVector(head_pose));
644 638
645 if (web_vr_mode_) {
646 DrawWebVr();
647
648 // When using async reprojection, we need to know which pose was used in
649 // the WebVR app for drawing this frame. Due to unknown amounts of
650 // buffering in the compositor and SurfaceTexture, we read the pose number
651 // from a corner pixel. There's no point in doing this for legacy
652 // distortion rendering since that doesn't need a pose, and reading back
653 // pixels is an expensive operation. TODO(klausw,crbug.com/655722): stop
654 // doing this once we have working no-compositor rendering for WebVR.
655 if (gvr_api_->GetAsyncReprojectionEnabled()) {
656 int pose_index_byte = GetPixelEncodedPoseIndexByte();
657 if (WebVrPoseByteIsValid(pose_index_byte)) {
658 // We have a valid pose, use it for reprojection.
659 webvr_left_viewport_->SetReprojection(GVR_REPROJECTION_FULL);
660 webvr_right_viewport_->SetReprojection(GVR_REPROJECTION_FULL);
661 head_pose = webvr_head_pose_[pose_index_byte % kPoseRingBufferSize];
662 // We can't mark the used pose as invalid since unfortunately
663 // we have to reuse them. The compositor will re-submit stale
664 // frames on vsync, and we can't tell that this has happened
665 // until we've read the pose index from it, and at that point
666 // it's too late to skip rendering.
667 } else {
668 // If we don't get a valid frame ID back we shouldn't attempt
669 // to reproject by an invalid matrix, so turn off reprojection
670 // instead. Invalid poses can permanently break reprojection
671 // for this GVR instance: http://crbug.com/667327
672 webvr_left_viewport_->SetReprojection(GVR_REPROJECTION_NONE);
673 webvr_right_viewport_->SetReprojection(GVR_REPROJECTION_NONE);
674 }
675 }
676 }
677
678 DrawVrShell(head_pose, frame); 639 DrawVrShell(head_pose, frame);
679 640
680 frame.Unbind(); 641 frame.Unbind();
681 frame.Submit(*buffer_viewport_list_, head_pose); 642 frame.Submit(*buffer_viewport_list_, head_pose);
682 643
683 // No need to swap buffers for surfaceless rendering. 644 // No need to swap buffers for surfaceless rendering.
684 if (surfaceless_rendering_) { 645 if (surfaceless_rendering_) {
685 ScheduleNextDrawFrame(); 646 ScheduleNextDrawFrame();
686 return; 647 return;
687 } 648 }
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
966 if (ui_surface_texture_.get()) 927 if (ui_surface_texture_.get())
967 ui_surface_texture_->SetDefaultBufferSize(width, height); 928 ui_surface_texture_->SetDefaultBufferSize(width, height);
968 ui_tex_physical_size_.width = width; 929 ui_tex_physical_size_.width = width;
969 ui_tex_physical_size_.height = height; 930 ui_tex_physical_size_.height = height;
970 } 931 }
971 932
972 base::WeakPtr<VrShellGl> VrShellGl::GetWeakPtr() { 933 base::WeakPtr<VrShellGl> VrShellGl::GetWeakPtr() {
973 return weak_ptr_factory_.GetWeakPtr(); 934 return weak_ptr_factory_.GetWeakPtr();
974 } 935 }
975 936
976 void VrShellGl::UpdateVSyncParameters(const base::TimeTicks timebase,
977 const base::TimeDelta interval) {
978 vsync_timebase_ = timebase;
979 vsync_interval_ = interval;
980 }
981
982 void VrShellGl::ScheduleNextDrawFrame() { 937 void VrShellGl::ScheduleNextDrawFrame() {
983 base::TimeTicks now = base::TimeTicks::Now(); 938 base::TimeTicks now = base::TimeTicks::Now();
984 base::TimeTicks target; 939 base::TimeTicks target;
985 940
986 if (vsync_interval_.is_zero()) { 941 if (vsync_interval_.is_zero()) {
987 target = now; 942 target = now;
988 } else { 943 } else {
989 target = now + vsync_interval_; 944 target = now + vsync_interval_;
990 int64_t intervals = (target - vsync_timebase_) / vsync_interval_; 945 int64_t intervals = (target - vsync_timebase_) / vsync_interval_;
991 target = vsync_timebase_ + intervals * vsync_interval_; 946 target = vsync_timebase_ + intervals * vsync_interval_;
992 } 947 }
948 task_runner_->PostDelayedTask(FROM_HERE, draw_task_.callback(), target - now);
993 949
994 task_runner_->PostDelayedTask(FROM_HERE, draw_task_.callback(), target - now); 950 if (!client_.is_bound())
951 return;
952 int64_t intervals = (target - vsync_timebase_) / vsync_interval_;
953 double time = (intervals * vsync_interval_).InSecondsF();
954 if (!pending_ack_) {
955 client_->OnVSync(
956 GetPose(), time,
957 base::Bind(&VrShellGl::OnVSyncAck, weak_ptr_factory_.GetWeakPtr()));
958 pending_ack_ = true;
959 } else {
960 pending_vsync_ = true;
961 pending_time_ = time;
962 }
995 } 963 }
996 964
997 void VrShellGl::ForceExitVr() { 965 void VrShellGl::ForceExitVr() {
998 main_thread_task_runner_->PostTask( 966 main_thread_task_runner_->PostTask(
999 FROM_HERE, base::Bind(&VrShell::ForceExitVr, weak_vr_shell_)); 967 FROM_HERE, base::Bind(&VrShell::ForceExitVr, weak_vr_shell_));
1000 } 968 }
1001 969
970 void VrShellGl::OnVRVSyncProviderClientConnected(
971 device::mojom::VRVSyncProviderClientPtr client) {
972 client_.Bind(client.PassInterface());
973 }
974
975 void VrShellGl::OnVSyncAck() {
976 pending_ack_ = false;
977 if (!pending_vsync_) {
978 triggered_vsync_from_ack_ = false;
979 return;
980 }
981 pending_vsync_ = false;
982 if (triggered_vsync_from_ack_)
983 return;
984 if (!client_.is_bound())
985 return;
986
987 // Allow VSyncAck to trigger a VSync in the case that we missed the previous
988 // frame to make it less likely multiple frames are missed in a row. However,
989 // we don't want to get into a state where VSync is only ever triggered from
990 // VSyncAck so we make sure the next VSync is really from a VSync and not an
991 // Ack.
992 client_->OnVSync(
993 GetPose(), pending_time_,
994 base::Bind(&VrShellGl::OnVSyncAck, weak_ptr_factory_.GetWeakPtr()));
995 pending_ack_ = true;
996 triggered_vsync_from_ack_ = true;
997 }
998
999 void VrShellGl::UpdateVSyncInterval(long timebase_nanos,
1000 double interval_seconds) {
1001 vsync_timebase_ = base::TimeTicks();
1002 vsync_timebase_ += base::TimeDelta::FromMicroseconds(timebase_nanos / 1000);
1003 vsync_interval_ = base::TimeDelta::FromSecondsD(interval_seconds);
1004 }
1005
1002 void VrShellGl::UpdateScene(std::unique_ptr<base::ListValue> commands) { 1006 void VrShellGl::UpdateScene(std::unique_ptr<base::ListValue> commands) {
1003 scene_->HandleCommands(std::move(commands), TimeInMicroseconds()); 1007 scene_->HandleCommands(std::move(commands), TimeInMicroseconds());
1004 } 1008 }
1005 1009
1010 device::mojom::VRPosePtr VrShellGl::GetPose() {
1011 TRACE_EVENT0("input", "GvrDevice::GetSensorState");
1012
1013 device::mojom::VRPosePtr pose = device::mojom::VRPose::New();
1014
1015 pose->timestamp = base::Time::Now().ToJsTime();
1016
1017 // Increment pose frame counter always, even if it's a faked pose.
1018 pose->poseIndex = ++pose_index_;
1019
1020 pose->orientation.emplace(4);
1021
1022 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow();
1023 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos;
1024
1025 gvr::Mat4f head_mat =
1026 gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time);
1027 head_mat = gvr_api_->ApplyNeckModel(head_mat, 1.0f);
1028
1029 // Save the underlying GVR pose for use by rendering. It can't use a
1030 // VRPosePtr since that's a different data type.
1031 webvr_head_pose_[pose_index_ % kPoseRingBufferSize] = head_mat;
1032
1033 gfx::Transform inv_transform(
1034 head_mat.m[0][0], head_mat.m[0][1], head_mat.m[0][2], head_mat.m[0][3],
1035 head_mat.m[1][0], head_mat.m[1][1], head_mat.m[1][2], head_mat.m[1][3],
1036 head_mat.m[2][0], head_mat.m[2][1], head_mat.m[2][2], head_mat.m[2][3],
1037 head_mat.m[3][0], head_mat.m[3][1], head_mat.m[3][2], head_mat.m[3][3]);
1038
1039 gfx::Transform transform;
1040 if (inv_transform.GetInverse(&transform)) {
1041 gfx::DecomposedTransform decomposed_transform;
1042 gfx::DecomposeTransform(&decomposed_transform, transform);
1043
1044 pose->orientation.value()[0] = decomposed_transform.quaternion[0];
1045 pose->orientation.value()[1] = decomposed_transform.quaternion[1];
1046 pose->orientation.value()[2] = decomposed_transform.quaternion[2];
1047 pose->orientation.value()[3] = decomposed_transform.quaternion[3];
1048
1049 pose->position.emplace(3);
1050 pose->position.value()[0] = decomposed_transform.translate[0];
1051 pose->position.value()[1] = decomposed_transform.translate[1];
1052 pose->position.value()[2] = decomposed_transform.translate[2];
1053 }
1054
1055 return pose;
1056 }
1057
1006 } // namespace vr_shell 1058 } // namespace vr_shell
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698