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

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

Issue 2430543002: Draw WebVR security overlay with a non-reprojected viewport (Closed)
Patch Set: Addressed Klaus' feedback Created 4 years, 2 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.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
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
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
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
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
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
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
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
OLDNEW
« chrome/browser/android/vr_shell/vr_shell.h ('K') | « chrome/browser/android/vr_shell/vr_shell.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698