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_scene.h" | 9 #include "chrome/browser/android/vr_shell/ui_scene.h" |
10 #include "chrome/browser/android/vr_shell/vr_compositor.h" | 10 #include "chrome/browser/android/vr_shell/vr_compositor.h" |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
75 // Positions and sizes of statically placed UI elements in the UI texture. | 75 // Positions and sizes of statically placed UI elements in the UI texture. |
76 // TODO(klausw): replace the hardcoded positions with JS position/offset | 76 // TODO(klausw): replace the hardcoded positions with JS position/offset |
77 // retrieval once the infrastructure for that is hooked up. | 77 // retrieval once the infrastructure for that is hooked up. |
78 // | 78 // |
79 // UI is designed with 1 pixel = 1mm at 1m distance. It's rescaled to | 79 // UI is designed with 1 pixel = 1mm at 1m distance. It's rescaled to |
80 // maintain the same angular resolution if placed closer or further. | 80 // maintain the same angular resolution if placed closer or further. |
81 // The warning overlays should be fairly close since they cut holes | 81 // The warning overlays should be fairly close since they cut holes |
82 // into geometry (they ignore the Z buffer), leading to odd effects | 82 // into geometry (they ignore the Z buffer), leading to odd effects |
83 // if they are far away. | 83 // if they are far away. |
84 static constexpr vr_shell::Recti kWebVrWarningTransientRect = { | 84 static constexpr vr_shell::Recti kWebVrWarningTransientRect = { |
85 0, 128, 512, 256}; | 85 0, 128, 512, 250}; |
86 static constexpr vr_shell::Recti kWebVrWarningPermanentRect = {0, 0, 512, 128}; | 86 static constexpr vr_shell::Recti kWebVrWarningPermanentRect = {0, 0, 512, 128}; |
87 static constexpr float kWebVrWarningDistance = 0.7f; // meters | 87 static constexpr float kWebVrWarningDistance = 0.7f; // meters |
88 static constexpr float kWebVrWarningPermanentAngle = 16.3f; // degrees up | 88 static constexpr float kWebVrWarningPermanentAngle = 16.3f; // degrees up |
89 // How long the transient warning needs to be displayed. | 89 // How long the transient warning needs to be displayed. |
90 static constexpr int64_t kWebVrWarningSeconds = 30; | 90 static constexpr int64_t kWebVrWarningSeconds = 30; |
91 | 91 |
92 static constexpr int kFramePrimaryBuffer = 0; | |
93 static constexpr int kFrameOverlayBuffer = 1; | |
klausw
2016/10/21 18:32:42
rename to kFrameHeadLockedBuffer ?
| |
94 | |
92 vr_shell::VrShell* g_instance; | 95 vr_shell::VrShell* g_instance; |
93 | 96 |
94 static const char kVrShellUIURL[] = "chrome://vr-shell-ui"; | 97 static const char kVrShellUIURL[] = "chrome://vr-shell-ui"; |
95 | 98 |
96 float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) { | 99 float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) { |
97 float xdiff = (vec1.x - vec2.x); | 100 float xdiff = (vec1.x - vec2.x); |
98 float ydiff = (vec1.y - vec2.y); | 101 float ydiff = (vec1.y - vec2.y); |
99 float zdiff = (vec1.z - vec2.z); | 102 float zdiff = (vec1.z - vec2.z); |
100 float scale = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff; | 103 float scale = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff; |
101 return std::sqrt(scale); | 104 return std::sqrt(scale); |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
238 CHECK(gl::GetGLImplementation() != gl::kGLImplementationNone || | 241 CHECK(gl::GetGLImplementation() != gl::kGLImplementationNone || |
239 gl::init::InitializeGLOneOff()); | 242 gl::init::InitializeGLOneOff()); |
240 | 243 |
241 content_texture_id_ = content_texture_handle; | 244 content_texture_id_ = content_texture_handle; |
242 ui_texture_id_ = ui_texture_handle; | 245 ui_texture_id_ = ui_texture_handle; |
243 | 246 |
244 gvr_api_->InitializeGl(); | 247 gvr_api_->InitializeGl(); |
245 std::vector<gvr::BufferSpec> specs; | 248 std::vector<gvr::BufferSpec> specs; |
246 specs.push_back(gvr_api_->CreateBufferSpec()); | 249 specs.push_back(gvr_api_->CreateBufferSpec()); |
247 render_size_ = specs[0].GetSize(); | 250 render_size_ = specs[0].GetSize(); |
251 | |
252 // For WebVR content | |
253 specs.push_back(gvr_api_->CreateBufferSpec()); | |
254 | |
248 swap_chain_.reset(new gvr::SwapChain(gvr_api_->CreateSwapChain(specs))); | 255 swap_chain_.reset(new gvr::SwapChain(gvr_api_->CreateSwapChain(specs))); |
249 | 256 |
250 vr_shell_renderer_.reset(new VrShellRenderer()); | 257 vr_shell_renderer_.reset(new VrShellRenderer()); |
251 buffer_viewport_list_.reset( | 258 buffer_viewport_list_.reset( |
252 new gvr::BufferViewportList(gvr_api_->CreateEmptyBufferViewportList())); | 259 new gvr::BufferViewportList(gvr_api_->CreateEmptyBufferViewportList())); |
260 buffer_viewport_list_->SetToRecommendedBufferViewports(); | |
261 | |
253 buffer_viewport_.reset( | 262 buffer_viewport_.reset( |
254 new gvr::BufferViewport(gvr_api_->CreateBufferViewport())); | 263 new gvr::BufferViewport(gvr_api_->CreateBufferViewport())); |
264 | |
265 overlay_left_viewport_.reset( | |
bshe
2016/10/21 19:00:04
nit: if you rename the above constexpr to HeadLock
| |
266 new gvr::BufferViewport(gvr_api_->CreateBufferViewport())); | |
267 buffer_viewport_list_->GetBufferViewport(GVR_LEFT_EYE, | |
268 overlay_left_viewport_.get()); | |
269 overlay_left_viewport_->SetSourceBufferIndex(kFrameOverlayBuffer); | |
270 overlay_left_viewport_->SetReprojection(GVR_REPROJECTION_NONE); | |
271 | |
272 overlay_right_viewport_.reset( | |
273 new gvr::BufferViewport(gvr_api_->CreateBufferViewport())); | |
274 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE, | |
275 overlay_right_viewport_.get()); | |
276 overlay_right_viewport_->SetSourceBufferIndex(kFrameOverlayBuffer); | |
277 overlay_right_viewport_->SetReprojection(GVR_REPROJECTION_NONE); | |
255 } | 278 } |
256 | 279 |
257 void VrShell::UpdateController(const gvr::Vec3f& forward_vector) { | 280 void VrShell::UpdateController(const gvr::Vec3f& forward_vector) { |
258 controller_->UpdateState(); | 281 controller_->UpdateState(); |
259 std::unique_ptr<VrGesture> gesture = controller_->DetectGesture(); | 282 std::unique_ptr<VrGesture> gesture = controller_->DetectGesture(); |
260 | 283 |
261 // TODO(asimjour) for now, scroll is sent to the main content. | 284 // TODO(asimjour) for now, scroll is sent to the main content. |
262 if (gesture->type == WebInputEvent::GestureScrollBegin || | 285 if (gesture->type == WebInputEvent::GestureScrollBegin || |
263 gesture->type == WebInputEvent::GestureScrollUpdate || | 286 gesture->type == WebInputEvent::GestureScrollUpdate || |
264 gesture->type == WebInputEvent::GestureScrollEnd) { | 287 gesture->type == WebInputEvent::GestureScrollEnd) { |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
409 gvr::Vec3f position = GetTranslation(head_pose); | 432 gvr::Vec3f position = GetTranslation(head_pose); |
410 if (position.x == 0.0f && position.y == 0.0f && position.z == 0.0f) { | 433 if (position.x == 0.0f && position.y == 0.0f && position.z == 0.0f) { |
411 // This appears to be a 3DOF pose without a neck model. Add one. | 434 // This appears to be a 3DOF pose without a neck model. Add one. |
412 // The head pose has redundant data. Assume we're only using the | 435 // The head pose has redundant data. Assume we're only using the |
413 // object_from_reference_matrix, we're not updating position_external. | 436 // object_from_reference_matrix, we're not updating position_external. |
414 // TODO: Not sure what object_from_reference_matrix is. The new api removed | 437 // TODO: Not sure what object_from_reference_matrix is. The new api removed |
415 // it. For now, removing it seems working fine. | 438 // it. For now, removing it seems working fine. |
416 gvr_api_->ApplyNeckModel(head_pose, 1.0f); | 439 gvr_api_->ApplyNeckModel(head_pose, 1.0f); |
417 } | 440 } |
418 | 441 |
419 // Bind back to the default framebuffer. | 442 // Bind the primary framebuffer. |
420 frame.BindBuffer(0); | 443 frame.BindBuffer(kFramePrimaryBuffer); |
421 | 444 |
422 if (webvr_mode_) { | 445 if (webvr_mode_) { |
423 DrawWebVr(); | 446 DrawWebVr(); |
424 if (!webvr_secure_origin_) { | 447 // Wait for the DOM contents to be loaded before rendering to avoid drawing |
448 // white rectangles with no content. | |
449 if (!webvr_secure_origin_ && IsUiTextureReady()) { | |
450 size_t last_viewport = buffer_viewport_list_->GetSize(); | |
451 buffer_viewport_list_->SetBufferViewport(last_viewport++, | |
452 *overlay_left_viewport_); | |
453 buffer_viewport_list_->SetBufferViewport(last_viewport++, | |
454 *overlay_right_viewport_); | |
455 | |
456 // Bind the non-reprojected overlay framebuffer. | |
457 frame.BindBuffer(kFrameOverlayBuffer); | |
425 DrawWebVrOverlay(target_time.monotonic_system_time_nanos); | 458 DrawWebVrOverlay(target_time.monotonic_system_time_nanos); |
426 } | 459 } |
427 | 460 |
428 // When using async reprojection, we need to know which pose was used in | 461 // When using async reprojection, we need to know which pose was used in |
429 // the WebVR app for drawing this frame. Due to unknown amounts of | 462 // the WebVR app for drawing this frame. Due to unknown amounts of |
430 // buffering in the compositor and SurfaceTexture, we read the pose number | 463 // buffering in the compositor and SurfaceTexture, we read the pose number |
431 // from a corner pixel. There's no point in doing this for legacy | 464 // from a corner pixel. There's no point in doing this for legacy |
432 // distortion rendering since that doesn't need a pose, and reading back | 465 // distortion rendering since that doesn't need a pose, and reading back |
433 // pixels is an expensive operation. TODO(klausw): stop doing this once we | 466 // pixels is an expensive operation. TODO(klausw): stop doing this once we |
434 // have working no-compositor rendering for WebVR. | 467 // have working no-compositor rendering for WebVR. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
493 view_matrix); | 526 view_matrix); |
494 | 527 |
495 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | 528 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
496 | 529 |
497 // TODO(mthiesse): Draw order for transparency. | 530 // TODO(mthiesse): Draw order for transparency. |
498 DrawUI(render_matrix); | 531 DrawUI(render_matrix); |
499 DrawCursor(render_matrix); | 532 DrawCursor(render_matrix); |
500 } | 533 } |
501 | 534 |
502 bool VrShell::IsUiTextureReady() { | 535 bool VrShell::IsUiTextureReady() { |
503 return ui_tex_width_ > 0 && ui_tex_height_ > 0; | 536 return ui_tex_width_ > 0 && ui_tex_height_ > 0 && dom_contents_loaded_; |
504 } | 537 } |
505 | 538 |
506 Rectf VrShell::MakeUiGlCopyRect(Recti pixel_rect) { | 539 Rectf VrShell::MakeUiGlCopyRect(Recti pixel_rect) { |
507 CHECK(IsUiTextureReady()); | 540 CHECK(IsUiTextureReady()); |
508 return Rectf({ | 541 return Rectf({ |
509 static_cast<float>(pixel_rect.x) / ui_tex_width_, | 542 static_cast<float>(pixel_rect.x) / ui_tex_width_, |
510 static_cast<float>(pixel_rect.y) / ui_tex_height_, | 543 static_cast<float>(pixel_rect.y) / ui_tex_height_, |
511 static_cast<float>(pixel_rect.width) / ui_tex_width_, | 544 static_cast<float>(pixel_rect.width) / ui_tex_width_, |
512 static_cast<float>(pixel_rect.height) / ui_tex_height_}); | 545 static_cast<float>(pixel_rect.height) / ui_tex_height_}); |
513 } | 546 } |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
632 void VrShell::DrawWebVrOverlay(int64_t present_time_nanos) { | 665 void VrShell::DrawWebVrOverlay(int64_t present_time_nanos) { |
633 // Draw WebVR security warning overlays for each eye. This uses the | 666 // Draw WebVR security warning overlays for each eye. This uses the |
634 // eye-from-head matrices but not the pose, goal is to place the icons in an | 667 // eye-from-head matrices but not the pose, goal is to place the icons in an |
635 // eye-relative position so that they follow along with head rotations. | 668 // eye-relative position so that they follow along with head rotations. |
636 | 669 |
637 gvr::Mat4f left_eye_view_matrix = | 670 gvr::Mat4f left_eye_view_matrix = |
638 gvr_api_->GetEyeFromHeadMatrix(GVR_LEFT_EYE); | 671 gvr_api_->GetEyeFromHeadMatrix(GVR_LEFT_EYE); |
639 gvr::Mat4f right_eye_view_matrix = | 672 gvr::Mat4f right_eye_view_matrix = |
640 gvr_api_->GetEyeFromHeadMatrix(GVR_RIGHT_EYE); | 673 gvr_api_->GetEyeFromHeadMatrix(GVR_RIGHT_EYE); |
641 | 674 |
675 glClear(GL_COLOR_BUFFER_BIT); | |
676 | |
642 buffer_viewport_list_->GetBufferViewport(GVR_LEFT_EYE, | 677 buffer_viewport_list_->GetBufferViewport(GVR_LEFT_EYE, |
643 buffer_viewport_.get()); | 678 buffer_viewport_.get()); |
644 DrawWebVrEye(left_eye_view_matrix, *buffer_viewport_, present_time_nanos); | 679 DrawWebVrEye(left_eye_view_matrix, *buffer_viewport_, present_time_nanos); |
645 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE, | 680 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE, |
646 buffer_viewport_.get()); | 681 buffer_viewport_.get()); |
647 DrawWebVrEye(right_eye_view_matrix, *buffer_viewport_, present_time_nanos); | 682 DrawWebVrEye(right_eye_view_matrix, *buffer_viewport_, present_time_nanos); |
648 } | 683 } |
649 | 684 |
650 void VrShell::DrawWebVrEye(const gvr::Mat4f& view_matrix, | 685 void VrShell::DrawWebVrEye(const gvr::Mat4f& view_matrix, |
651 const gvr::BufferViewport& params, | 686 const gvr::BufferViewport& params, |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
742 void VrShell::OnDomContentsLoaded() { | 777 void VrShell::OnDomContentsLoaded() { |
743 // TODO(mthiesse): Setting the background to transparent after the DOM content | 778 // TODO(mthiesse): Setting the background to transparent after the DOM content |
744 // has loaded is a hack to work around the background not updating when we set | 779 // has loaded is a hack to work around the background not updating when we set |
745 // it to transparent unless we perform a very specific sequence of events. | 780 // it to transparent unless we perform a very specific sequence of events. |
746 // First the page background must load as not transparent, then we set the | 781 // First the page background must load as not transparent, then we set the |
747 // background of the renderer to transparent, then we update the page | 782 // background of the renderer to transparent, then we update the page |
748 // background to be transparent. This is probably a bug in blink that we | 783 // background to be transparent. This is probably a bug in blink that we |
749 // should fix. | 784 // should fix. |
750 ui_contents_->GetRenderWidgetHostView()->SetBackgroundColor( | 785 ui_contents_->GetRenderWidgetHostView()->SetBackgroundColor( |
751 SK_ColorTRANSPARENT); | 786 SK_ColorTRANSPARENT); |
787 | |
788 dom_contents_loaded_ = true; | |
klausw
2016/10/21 17:50:47
I'm a bit fuzzy about how the life cycle works, do
cjgrant
2016/10/21 18:29:02
See previous comments. Native state changes (like
| |
752 } | 789 } |
753 | 790 |
754 void VrShell::SetWebVrMode(JNIEnv* env, | 791 void VrShell::SetWebVrMode(JNIEnv* env, |
755 const base::android::JavaParamRef<jobject>& obj, | 792 const base::android::JavaParamRef<jobject>& obj, |
756 bool enabled) { | 793 bool enabled) { |
757 webvr_mode_ = enabled; | 794 webvr_mode_ = enabled; |
758 if (enabled) { | 795 if (enabled) { |
759 int64_t now = gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos; | 796 int64_t now = gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos; |
760 constexpr int64_t seconds_to_nanos = 1000 * 1000 * 1000; | 797 constexpr int64_t seconds_to_nanos = 1000 * 1000 * 1000; |
761 webvr_warning_end_nanos_ = now + kWebVrWarningSeconds * seconds_to_nanos; | 798 webvr_warning_end_nanos_ = now + kWebVrWarningSeconds * seconds_to_nanos; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
867 const JavaParamRef<jobject>& ui_web_contents, | 904 const JavaParamRef<jobject>& ui_web_contents, |
868 jlong ui_window_android) { | 905 jlong ui_window_android) { |
869 return reinterpret_cast<intptr_t>(new VrShell( | 906 return reinterpret_cast<intptr_t>(new VrShell( |
870 env, obj, content::WebContents::FromJavaWebContents(content_web_contents), | 907 env, obj, content::WebContents::FromJavaWebContents(content_web_contents), |
871 reinterpret_cast<ui::WindowAndroid*>(content_window_android), | 908 reinterpret_cast<ui::WindowAndroid*>(content_window_android), |
872 content::WebContents::FromJavaWebContents(ui_web_contents), | 909 content::WebContents::FromJavaWebContents(ui_web_contents), |
873 reinterpret_cast<ui::WindowAndroid*>(ui_window_android))); | 910 reinterpret_cast<ui::WindowAndroid*>(ui_window_android))); |
874 } | 911 } |
875 | 912 |
876 } // namespace vr_shell | 913 } // namespace vr_shell |
OLD | NEW |