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.h" | 5 #include "chrome/browser/android/vr_shell/vr_shell.h" |
| 6 | 6 |
| 7 #include "base/metrics/histogram_macros.h" | 7 #include "base/metrics/histogram_macros.h" |
| 8 #include "chrome/browser/android/vr_shell/ui_elements.h" | 8 #include "chrome/browser/android/vr_shell/ui_elements.h" |
| 9 #include "chrome/browser/android/vr_shell/ui_interface.h" | 9 #include "chrome/browser/android/vr_shell/ui_interface.h" |
| 10 #include "chrome/browser/android/vr_shell/ui_scene.h" | 10 #include "chrome/browser/android/vr_shell/ui_scene.h" |
| (...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 535 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); | 535 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); |
| 536 } | 536 } |
| 537 gesture->type = WebInputEvent::GestureTapDown; | 537 gesture->type = WebInputEvent::GestureTapDown; |
| 538 gesture->data.tapDown.width = pixel_x; | 538 gesture->data.tapDown.width = pixel_x; |
| 539 gesture->data.tapDown.height = pixel_y; | 539 gesture->data.tapDown.height = pixel_y; |
| 540 current_input_target_->ProcessUpdatedGesture(*gesture.get()); | 540 current_input_target_->ProcessUpdatedGesture(*gesture.get()); |
| 541 } | 541 } |
| 542 } | 542 } |
| 543 | 543 |
| 544 void VrShell::SetGvrPoseForWebVr(const gvr::Mat4f& pose, uint32_t pose_num) { | 544 void VrShell::SetGvrPoseForWebVr(const gvr::Mat4f& pose, uint32_t pose_num) { |
| 545 webvr_pose_index_max_ = pose_num; | |
| 545 webvr_head_pose_[pose_num % kPoseRingBufferSize] = pose; | 546 webvr_head_pose_[pose_num % kPoseRingBufferSize] = pose; |
| 546 } | 547 } |
| 547 | 548 |
| 548 uint32_t GetPixelEncodedPoseIndex() { | 549 uint32_t GetPixelEncodedPoseIndex() { |
| 549 TRACE_EVENT0("gpu", "VrShell::GetPixelEncodedPoseIndex"); | 550 TRACE_EVENT0("gpu", "VrShell::GetPixelEncodedPoseIndex"); |
| 550 // Read the pose index encoded in a bottom left pixel as color values. | 551 // Read the pose index encoded in a bottom left pixel as color values. |
| 551 // See also third_party/WebKit/Source/modules/vr/VRDisplay.cpp which | 552 // See also third_party/WebKit/Source/modules/vr/VRDisplay.cpp which |
| 552 // encodes the pose index, and device/vr/android/gvr/gvr_device.cc | 553 // encodes the pose index, and device/vr/android/gvr/gvr_device.cc |
| 553 // which tracks poses. | 554 // which tracks poses. |
| 554 uint8_t pixels[4]; | 555 uint8_t pixels[4]; |
| 555 // Assume we're reading from the framebuffer we just wrote to. | 556 // Assume we're reading from the framebuffer we just wrote to. |
| 556 // That's true currently, we may need to use glReadBuffer(GL_BACK) | 557 // That's true currently, we may need to use glReadBuffer(GL_BACK) |
| 557 // or equivalent if the rendering setup changes in the future. | 558 // or equivalent if the rendering setup changes in the future. |
| 558 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels); | 559 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels); |
| 559 return pixels[0] | (pixels[1] << 8) | (pixels[2] << 16); | 560 return pixels[0] | (pixels[1] << 8) | (pixels[2] << 16); |
| 560 } | 561 } |
| 561 | 562 |
| 563 bool VrShell::WebVrPoseIsValid(uint32_t pose_frame) { | |
|
mthiesse
2016/12/01 15:39:11
This doesn't guarantee the pose is valid; we shoul
klausw
2016/12/01 16:10:18
Will do, in earlier versions I did have a magic nu
klausw
2016/12/01 19:50:41
Added a 16-bit magic number. Currently hardcoded s
| |
| 564 // Ignore pose numbers that are zero or larger than any known pose | |
| 565 // index. This helps avoid glitches from garbage data in the render | |
| 566 // buffer that can appear during initialization or resizing. These | |
| 567 // often appear as flashes of all-black or all-white pixels. | |
| 568 if (pose_frame == 0 || pose_frame > webvr_pose_index_max_) { | |
| 569 VLOG(1) << "WebVR: reject decoded pose index " << pose_frame << | |
| 570 ", highest seen is " << webvr_pose_index_max_; | |
| 571 return false; | |
| 572 } | |
| 573 return true; | |
| 574 } | |
| 575 | |
| 562 void VrShell::DrawFrame(JNIEnv* env, const JavaParamRef<jobject>& obj) { | 576 void VrShell::DrawFrame(JNIEnv* env, const JavaParamRef<jobject>& obj) { |
| 563 TRACE_EVENT0("gpu", "VrShell::DrawFrame"); | 577 TRACE_EVENT0("gpu", "VrShell::DrawFrame"); |
| 564 // Reset the viewport list to just the pair of viewports for the | 578 // Reset the viewport list to just the pair of viewports for the |
| 565 // primary buffer each frame. Head-locked viewports get added by | 579 // primary buffer each frame. Head-locked viewports get added by |
| 566 // DrawVrShell if needed. | 580 // DrawVrShell if needed. |
| 567 buffer_viewport_list_->SetToRecommendedBufferViewports(); | 581 buffer_viewport_list_->SetToRecommendedBufferViewports(); |
| 568 | 582 |
| 569 if (html_interface_->GetMode() == UiInterface::Mode::WEB_VR) { | 583 if (html_interface_->GetMode() == UiInterface::Mode::WEB_VR) { |
| 570 // If needed, resize the primary buffer for use with WebVR. | 584 // If needed, resize the primary buffer for use with WebVR. |
| 571 if (render_size_primary_ != render_size_primary_webvr_) { | 585 if (render_size_primary_ != render_size_primary_webvr_) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 616 | 630 |
| 617 // When using async reprojection, we need to know which pose was used in | 631 // 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 | 632 // the WebVR app for drawing this frame. Due to unknown amounts of |
| 619 // buffering in the compositor and SurfaceTexture, we read the pose number | 633 // 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 | 634 // 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 | 635 // distortion rendering since that doesn't need a pose, and reading back |
| 622 // pixels is an expensive operation. TODO(klausw,crbug.com/655722): stop | 636 // pixels is an expensive operation. TODO(klausw,crbug.com/655722): stop |
| 623 // doing this once we have working no-compositor rendering for WebVR. | 637 // doing this once we have working no-compositor rendering for WebVR. |
| 624 if (gvr_api_->GetAsyncReprojectionEnabled()) { | 638 if (gvr_api_->GetAsyncReprojectionEnabled()) { |
| 625 uint32_t webvr_pose_frame = GetPixelEncodedPoseIndex(); | 639 uint32_t webvr_pose_frame = GetPixelEncodedPoseIndex(); |
| 626 // If we don't get a valid frame ID back we shouldn't attempt to reproject | 640 if (WebVrPoseIsValid(webvr_pose_frame)) { |
| 627 // by an invalid matrix, so turn of reprojection instead. | 641 // We have a valid pose, use it for reprojection. |
| 628 if (webvr_pose_frame == 0) { | |
| 629 webvr_left_viewport_->SetReprojection(GVR_REPROJECTION_NONE); | |
| 630 webvr_right_viewport_->SetReprojection(GVR_REPROJECTION_NONE); | |
| 631 } else { | |
| 632 webvr_left_viewport_->SetReprojection(GVR_REPROJECTION_FULL); | 642 webvr_left_viewport_->SetReprojection(GVR_REPROJECTION_FULL); |
| 633 webvr_right_viewport_->SetReprojection(GVR_REPROJECTION_FULL); | 643 webvr_right_viewport_->SetReprojection(GVR_REPROJECTION_FULL); |
| 634 head_pose = webvr_head_pose_[webvr_pose_frame % kPoseRingBufferSize]; | 644 head_pose = webvr_head_pose_[webvr_pose_frame % kPoseRingBufferSize]; |
|
mthiesse
2016/12/01 15:39:11
You should make webvr_head_pose_ a vector of uniqu
klausw
2016/12/01 16:10:18
Poses do get reused unfortunately. The compositor
klausw
2016/12/01 19:50:41
Done, I've added a "valid" vector that's set to fa
| |
| 645 } else { | |
| 646 // If we don't get a valid frame ID back we shouldn't attempt | |
| 647 // to reproject by an invalid matrix, so turn off reprojection | |
| 648 // instead. Invalid poses can permanently break reprojection | |
| 649 // for this GVR instance: http://crbug.com/667327 | |
| 650 webvr_left_viewport_->SetReprojection(GVR_REPROJECTION_NONE); | |
| 651 webvr_right_viewport_->SetReprojection(GVR_REPROJECTION_NONE); | |
| 635 } | 652 } |
| 636 } | 653 } |
| 637 } | 654 } |
| 638 | 655 |
| 639 DrawVrShell(head_pose, frame); | 656 DrawVrShell(head_pose, frame); |
| 640 | 657 |
| 641 frame.Unbind(); | 658 frame.Unbind(); |
| 642 frame.Submit(*buffer_viewport_list_, head_pose); | 659 frame.Submit(*buffer_viewport_list_, head_pose); |
| 643 } | 660 } |
| 644 | 661 |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1053 const JavaParamRef<jobject>& ui_web_contents, | 1070 const JavaParamRef<jobject>& ui_web_contents, |
| 1054 jlong ui_window_android) { | 1071 jlong ui_window_android) { |
| 1055 return reinterpret_cast<intptr_t>(new VrShell( | 1072 return reinterpret_cast<intptr_t>(new VrShell( |
| 1056 env, obj, content::WebContents::FromJavaWebContents(content_web_contents), | 1073 env, obj, content::WebContents::FromJavaWebContents(content_web_contents), |
| 1057 reinterpret_cast<ui::WindowAndroid*>(content_window_android), | 1074 reinterpret_cast<ui::WindowAndroid*>(content_window_android), |
| 1058 content::WebContents::FromJavaWebContents(ui_web_contents), | 1075 content::WebContents::FromJavaWebContents(ui_web_contents), |
| 1059 reinterpret_cast<ui::WindowAndroid*>(ui_window_android))); | 1076 reinterpret_cast<ui::WindowAndroid*>(ui_window_android))); |
| 1060 } | 1077 } |
| 1061 | 1078 |
| 1062 } // namespace vr_shell | 1079 } // namespace vr_shell |
| OLD | NEW |