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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 // Positions and sizes of statically placed UI elements in the UI texture. | 76 // Positions and sizes of statically placed UI elements in the UI texture. |
77 // TODO(klausw): replace the hardcoded positions with JS position/offset | 77 // TODO(klausw): replace the hardcoded positions with JS position/offset |
78 // retrieval once the infrastructure for that is hooked up. | 78 // retrieval once the infrastructure for that is hooked up. |
79 // | 79 // |
80 // UI is designed with 1 pixel = 1mm at 1m distance. It's rescaled to | 80 // UI is designed with 1 pixel = 1mm at 1m distance. It's rescaled to |
81 // maintain the same angular resolution if placed closer or further. | 81 // maintain the same angular resolution if placed closer or further. |
82 // The warning overlays should be fairly close since they cut holes | 82 // The warning overlays should be fairly close since they cut holes |
83 // into geometry (they ignore the Z buffer), leading to odd effects | 83 // into geometry (they ignore the Z buffer), leading to odd effects |
84 // if they are far away. | 84 // if they are far away. |
85 static constexpr vr_shell::Recti kWebVrWarningTransientRect = { | 85 static constexpr vr_shell::Recti kWebVrWarningTransientRect = { |
86 0, 128, 512, 256}; | 86 0, 128, 512, 250}; |
87 static constexpr vr_shell::Recti kWebVrWarningPermanentRect = {0, 0, 512, 128}; | 87 static constexpr vr_shell::Recti kWebVrWarningPermanentRect = {0, 0, 512, 128}; |
88 static constexpr float kWebVrWarningDistance = 0.7f; // meters | 88 static constexpr float kWebVrWarningDistance = 0.7f; // meters |
89 static constexpr float kWebVrWarningPermanentAngle = 16.3f; // degrees up | 89 static constexpr float kWebVrWarningPermanentAngle = 16.3f; // degrees up |
90 // How long the transient warning needs to be displayed. | 90 // How long the transient warning needs to be displayed. |
91 static constexpr int64_t kWebVrWarningSeconds = 30; | 91 static constexpr int64_t kWebVrWarningSeconds = 30; |
92 | 92 |
| 93 static constexpr int kFramePrimaryBuffer = 0; |
| 94 static constexpr int kFrameHeadlockedBuffer = 1; |
| 95 |
93 vr_shell::VrShell* g_instance; | 96 vr_shell::VrShell* g_instance; |
94 | 97 |
95 static const char kVrShellUIURL[] = "chrome://vr-shell-ui"; | 98 static const char kVrShellUIURL[] = "chrome://vr-shell-ui"; |
96 | 99 |
97 float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) { | 100 float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) { |
98 float xdiff = (vec1.x - vec2.x); | 101 float xdiff = (vec1.x - vec2.x); |
99 float ydiff = (vec1.y - vec2.y); | 102 float ydiff = (vec1.y - vec2.y); |
100 float zdiff = (vec1.z - vec2.z); | 103 float zdiff = (vec1.z - vec2.z); |
101 float scale = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff; | 104 float scale = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff; |
102 return std::sqrt(scale); | 105 return std::sqrt(scale); |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 CHECK(gl::GetGLImplementation() != gl::kGLImplementationNone || | 243 CHECK(gl::GetGLImplementation() != gl::kGLImplementationNone || |
241 gl::init::InitializeGLOneOff()); | 244 gl::init::InitializeGLOneOff()); |
242 | 245 |
243 content_texture_id_ = content_texture_handle; | 246 content_texture_id_ = content_texture_handle; |
244 ui_texture_id_ = ui_texture_handle; | 247 ui_texture_id_ = ui_texture_handle; |
245 | 248 |
246 gvr_api_->InitializeGl(); | 249 gvr_api_->InitializeGl(); |
247 std::vector<gvr::BufferSpec> specs; | 250 std::vector<gvr::BufferSpec> specs; |
248 specs.push_back(gvr_api_->CreateBufferSpec()); | 251 specs.push_back(gvr_api_->CreateBufferSpec()); |
249 render_size_ = specs[0].GetSize(); | 252 render_size_ = specs[0].GetSize(); |
| 253 |
| 254 // For WebVR content |
| 255 specs.push_back(gvr_api_->CreateBufferSpec()); |
| 256 |
250 swap_chain_.reset(new gvr::SwapChain(gvr_api_->CreateSwapChain(specs))); | 257 swap_chain_.reset(new gvr::SwapChain(gvr_api_->CreateSwapChain(specs))); |
251 | 258 |
252 vr_shell_renderer_.reset(new VrShellRenderer()); | 259 vr_shell_renderer_.reset(new VrShellRenderer()); |
253 buffer_viewport_list_.reset( | 260 buffer_viewport_list_.reset( |
254 new gvr::BufferViewportList(gvr_api_->CreateEmptyBufferViewportList())); | 261 new gvr::BufferViewportList(gvr_api_->CreateEmptyBufferViewportList())); |
| 262 buffer_viewport_list_->SetToRecommendedBufferViewports(); |
| 263 |
255 buffer_viewport_.reset( | 264 buffer_viewport_.reset( |
256 new gvr::BufferViewport(gvr_api_->CreateBufferViewport())); | 265 new gvr::BufferViewport(gvr_api_->CreateBufferViewport())); |
| 266 |
| 267 headlocked_left_viewport_.reset( |
| 268 new gvr::BufferViewport(gvr_api_->CreateBufferViewport())); |
| 269 buffer_viewport_list_->GetBufferViewport(GVR_LEFT_EYE, |
| 270 headlocked_left_viewport_.get()); |
| 271 headlocked_left_viewport_->SetSourceBufferIndex(kFrameHeadlockedBuffer); |
| 272 headlocked_left_viewport_->SetReprojection(GVR_REPROJECTION_NONE); |
| 273 |
| 274 headlocked_right_viewport_.reset( |
| 275 new gvr::BufferViewport(gvr_api_->CreateBufferViewport())); |
| 276 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE, |
| 277 headlocked_right_viewport_.get()); |
| 278 headlocked_right_viewport_->SetSourceBufferIndex(kFrameHeadlockedBuffer); |
| 279 headlocked_right_viewport_->SetReprojection(GVR_REPROJECTION_NONE); |
257 } | 280 } |
258 | 281 |
259 void VrShell::UpdateController(const gvr::Vec3f& forward_vector) { | 282 void VrShell::UpdateController(const gvr::Vec3f& forward_vector) { |
260 controller_->UpdateState(); | 283 controller_->UpdateState(); |
261 std::unique_ptr<VrGesture> gesture = controller_->DetectGesture(); | 284 std::unique_ptr<VrGesture> gesture = controller_->DetectGesture(); |
262 | 285 |
263 // TODO(asimjour) for now, scroll is sent to the main content. | 286 // TODO(asimjour) for now, scroll is sent to the main content. |
264 if (gesture->type == WebInputEvent::GestureScrollBegin || | 287 if (gesture->type == WebInputEvent::GestureScrollBegin || |
265 gesture->type == WebInputEvent::GestureScrollUpdate || | 288 gesture->type == WebInputEvent::GestureScrollUpdate || |
266 gesture->type == WebInputEvent::GestureScrollEnd) { | 289 gesture->type == WebInputEvent::GestureScrollEnd) { |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
411 gvr::Vec3f position = GetTranslation(head_pose); | 434 gvr::Vec3f position = GetTranslation(head_pose); |
412 if (position.x == 0.0f && position.y == 0.0f && position.z == 0.0f) { | 435 if (position.x == 0.0f && position.y == 0.0f && position.z == 0.0f) { |
413 // This appears to be a 3DOF pose without a neck model. Add one. | 436 // This appears to be a 3DOF pose without a neck model. Add one. |
414 // The head pose has redundant data. Assume we're only using the | 437 // The head pose has redundant data. Assume we're only using the |
415 // object_from_reference_matrix, we're not updating position_external. | 438 // object_from_reference_matrix, we're not updating position_external. |
416 // TODO: Not sure what object_from_reference_matrix is. The new api removed | 439 // TODO: Not sure what object_from_reference_matrix is. The new api removed |
417 // it. For now, removing it seems working fine. | 440 // it. For now, removing it seems working fine. |
418 gvr_api_->ApplyNeckModel(head_pose, 1.0f); | 441 gvr_api_->ApplyNeckModel(head_pose, 1.0f); |
419 } | 442 } |
420 | 443 |
421 // Bind back to the default framebuffer. | 444 // Bind the primary framebuffer. |
422 frame.BindBuffer(0); | 445 frame.BindBuffer(kFramePrimaryBuffer); |
423 | 446 |
424 if (webvr_mode_) { | 447 if (webvr_mode_) { |
425 DrawWebVr(); | 448 DrawWebVr(); |
426 if (!webvr_secure_origin_) { | 449 // Wait for the DOM contents to be loaded before rendering to avoid drawing |
| 450 // white rectangles with no content. |
| 451 if (!webvr_secure_origin_ && IsUiTextureReady()) { |
| 452 size_t last_viewport = buffer_viewport_list_->GetSize(); |
| 453 buffer_viewport_list_->SetBufferViewport(last_viewport++, |
| 454 *headlocked_left_viewport_); |
| 455 buffer_viewport_list_->SetBufferViewport(last_viewport++, |
| 456 *headlocked_right_viewport_); |
| 457 |
| 458 // Bind the headlocked framebuffer. |
| 459 frame.BindBuffer(kFrameHeadlockedBuffer); |
427 DrawWebVrOverlay(target_time.monotonic_system_time_nanos); | 460 DrawWebVrOverlay(target_time.monotonic_system_time_nanos); |
428 } | 461 } |
429 | 462 |
430 // When using async reprojection, we need to know which pose was used in | 463 // When using async reprojection, we need to know which pose was used in |
431 // the WebVR app for drawing this frame. Due to unknown amounts of | 464 // the WebVR app for drawing this frame. Due to unknown amounts of |
432 // buffering in the compositor and SurfaceTexture, we read the pose number | 465 // buffering in the compositor and SurfaceTexture, we read the pose number |
433 // from a corner pixel. There's no point in doing this for legacy | 466 // from a corner pixel. There's no point in doing this for legacy |
434 // distortion rendering since that doesn't need a pose, and reading back | 467 // distortion rendering since that doesn't need a pose, and reading back |
435 // pixels is an expensive operation. TODO(klausw): stop doing this once we | 468 // pixels is an expensive operation. TODO(klausw): stop doing this once we |
436 // have working no-compositor rendering for WebVR. | 469 // have working no-compositor rendering for WebVR. |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 view_matrix); | 529 view_matrix); |
497 | 530 |
498 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | 531 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
499 | 532 |
500 // TODO(mthiesse): Draw order for transparency. | 533 // TODO(mthiesse): Draw order for transparency. |
501 DrawUI(world_render_matrix, fov_render_matrix); | 534 DrawUI(world_render_matrix, fov_render_matrix); |
502 DrawCursor(world_render_matrix); | 535 DrawCursor(world_render_matrix); |
503 } | 536 } |
504 | 537 |
505 bool VrShell::IsUiTextureReady() { | 538 bool VrShell::IsUiTextureReady() { |
506 return ui_tex_width_ > 0 && ui_tex_height_ > 0; | 539 return ui_tex_width_ > 0 && ui_tex_height_ > 0 && dom_contents_loaded_; |
507 } | 540 } |
508 | 541 |
509 Rectf VrShell::MakeUiGlCopyRect(Recti pixel_rect) { | 542 Rectf VrShell::MakeUiGlCopyRect(Recti pixel_rect) { |
510 CHECK(IsUiTextureReady()); | 543 CHECK(IsUiTextureReady()); |
511 return Rectf({ | 544 return Rectf({ |
512 static_cast<float>(pixel_rect.x) / ui_tex_width_, | 545 static_cast<float>(pixel_rect.x) / ui_tex_width_, |
513 static_cast<float>(pixel_rect.y) / ui_tex_height_, | 546 static_cast<float>(pixel_rect.y) / ui_tex_height_, |
514 static_cast<float>(pixel_rect.width) / ui_tex_width_, | 547 static_cast<float>(pixel_rect.width) / ui_tex_width_, |
515 static_cast<float>(pixel_rect.height) / ui_tex_height_}); | 548 static_cast<float>(pixel_rect.height) / ui_tex_height_}); |
516 } | 549 } |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
638 void VrShell::DrawWebVrOverlay(int64_t present_time_nanos) { | 671 void VrShell::DrawWebVrOverlay(int64_t present_time_nanos) { |
639 // Draw WebVR security warning overlays for each eye. This uses the | 672 // Draw WebVR security warning overlays for each eye. This uses the |
640 // eye-from-head matrices but not the pose, goal is to place the icons in an | 673 // eye-from-head matrices but not the pose, goal is to place the icons in an |
641 // eye-relative position so that they follow along with head rotations. | 674 // eye-relative position so that they follow along with head rotations. |
642 | 675 |
643 gvr::Mat4f left_eye_view_matrix = | 676 gvr::Mat4f left_eye_view_matrix = |
644 gvr_api_->GetEyeFromHeadMatrix(GVR_LEFT_EYE); | 677 gvr_api_->GetEyeFromHeadMatrix(GVR_LEFT_EYE); |
645 gvr::Mat4f right_eye_view_matrix = | 678 gvr::Mat4f right_eye_view_matrix = |
646 gvr_api_->GetEyeFromHeadMatrix(GVR_RIGHT_EYE); | 679 gvr_api_->GetEyeFromHeadMatrix(GVR_RIGHT_EYE); |
647 | 680 |
| 681 glClear(GL_COLOR_BUFFER_BIT); |
| 682 |
648 buffer_viewport_list_->GetBufferViewport(GVR_LEFT_EYE, | 683 buffer_viewport_list_->GetBufferViewport(GVR_LEFT_EYE, |
649 buffer_viewport_.get()); | 684 buffer_viewport_.get()); |
650 DrawWebVrEye(left_eye_view_matrix, *buffer_viewport_, present_time_nanos); | 685 DrawWebVrEye(left_eye_view_matrix, *buffer_viewport_, present_time_nanos); |
651 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE, | 686 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE, |
652 buffer_viewport_.get()); | 687 buffer_viewport_.get()); |
653 DrawWebVrEye(right_eye_view_matrix, *buffer_viewport_, present_time_nanos); | 688 DrawWebVrEye(right_eye_view_matrix, *buffer_viewport_, present_time_nanos); |
654 } | 689 } |
655 | 690 |
656 void VrShell::DrawWebVrEye(const gvr::Mat4f& view_matrix, | 691 void VrShell::DrawWebVrEye(const gvr::Mat4f& view_matrix, |
657 const gvr::BufferViewport& params, | 692 const gvr::BufferViewport& params, |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 // TODO(mthiesse): Setting the background to transparent after the DOM content | 784 // TODO(mthiesse): Setting the background to transparent after the DOM content |
750 // has loaded is a hack to work around the background not updating when we set | 785 // has loaded is a hack to work around the background not updating when we set |
751 // it to transparent unless we perform a very specific sequence of events. | 786 // it to transparent unless we perform a very specific sequence of events. |
752 // First the page background must load as not transparent, then we set the | 787 // First the page background must load as not transparent, then we set the |
753 // background of the renderer to transparent, then we update the page | 788 // background of the renderer to transparent, then we update the page |
754 // background to be transparent. This is probably a bug in blink that we | 789 // background to be transparent. This is probably a bug in blink that we |
755 // should fix. | 790 // should fix. |
756 ui_contents_->GetRenderWidgetHostView()->SetBackgroundColor( | 791 ui_contents_->GetRenderWidgetHostView()->SetBackgroundColor( |
757 SK_ColorTRANSPARENT); | 792 SK_ColorTRANSPARENT); |
758 html_interface_->OnDomContentsLoaded(); | 793 html_interface_->OnDomContentsLoaded(); |
| 794 dom_contents_loaded_ = true; |
759 } | 795 } |
760 | 796 |
761 void VrShell::SetWebVrMode(JNIEnv* env, | 797 void VrShell::SetWebVrMode(JNIEnv* env, |
762 const base::android::JavaParamRef<jobject>& obj, | 798 const base::android::JavaParamRef<jobject>& obj, |
763 bool enabled) { | 799 bool enabled) { |
764 webvr_mode_ = enabled; | 800 webvr_mode_ = enabled; |
765 if (enabled) { | 801 if (enabled) { |
766 int64_t now = gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos; | 802 int64_t now = gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos; |
767 constexpr int64_t seconds_to_nanos = 1000 * 1000 * 1000; | 803 constexpr int64_t seconds_to_nanos = 1000 * 1000 * 1000; |
768 webvr_warning_end_nanos_ = now + kWebVrWarningSeconds * seconds_to_nanos; | 804 webvr_warning_end_nanos_ = now + kWebVrWarningSeconds * seconds_to_nanos; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
880 const JavaParamRef<jobject>& ui_web_contents, | 916 const JavaParamRef<jobject>& ui_web_contents, |
881 jlong ui_window_android) { | 917 jlong ui_window_android) { |
882 return reinterpret_cast<intptr_t>(new VrShell( | 918 return reinterpret_cast<intptr_t>(new VrShell( |
883 env, obj, content::WebContents::FromJavaWebContents(content_web_contents), | 919 env, obj, content::WebContents::FromJavaWebContents(content_web_contents), |
884 reinterpret_cast<ui::WindowAndroid*>(content_window_android), | 920 reinterpret_cast<ui::WindowAndroid*>(content_window_android), |
885 content::WebContents::FromJavaWebContents(ui_web_contents), | 921 content::WebContents::FromJavaWebContents(ui_web_contents), |
886 reinterpret_cast<ui::WindowAndroid*>(ui_window_android))); | 922 reinterpret_cast<ui::WindowAndroid*>(ui_window_android))); |
887 } | 923 } |
888 | 924 |
889 } // namespace vr_shell | 925 } // namespace vr_shell |
OLD | NEW |