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

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

Issue 2436863002: Use the HTML UI to render WebVR warnings (Closed)
Patch Set: 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
« no previous file with comments | « chrome/browser/android/vr_shell/vr_shell.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 static constexpr float kReticleOffset = 0.99f; 66 static constexpr float kReticleOffset = 0.99f;
67 67
68 // Limit the rendering distance of the reticle to the distance to a corner of 68 // Limit the rendering distance of the reticle to the distance to a corner of
69 // the content quad, times this value. This lets the rendering distance 69 // the content quad, times this value. This lets the rendering distance
70 // adjust according to content quad placement. 70 // adjust according to content quad placement.
71 static constexpr float kReticleDistanceMultiplier = 1.5f; 71 static constexpr float kReticleDistanceMultiplier = 1.5f;
72 72
73 // UI element 0 is the browser content rectangle. 73 // UI element 0 is the browser content rectangle.
74 static constexpr int kBrowserUiElementId = 0; 74 static constexpr int kBrowserUiElementId = 0;
75 75
76 // Positions and sizes of statically placed UI elements in the UI texture.
77 // TODO(klausw): replace the hardcoded positions with JS position/offset
78 // retrieval once the infrastructure for that is hooked up.
79 //
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.
82 // The warning overlays should be fairly close since they cut holes
83 // into geometry (they ignore the Z buffer), leading to odd effects
84 // if they are far away.
85 static constexpr vr_shell::Recti kWebVrWarningTransientRect = {
86 0, 128, 512, 256};
87 static constexpr vr_shell::Recti kWebVrWarningPermanentRect = {0, 0, 512, 128};
88 static constexpr float kWebVrWarningDistance = 0.7f; // meters
89 static constexpr float kWebVrWarningPermanentAngle = 16.3f; // degrees up
90 // How long the transient warning needs to be displayed.
91 static constexpr int64_t kWebVrWarningSeconds = 30;
92
93 vr_shell::VrShell* g_instance; 76 vr_shell::VrShell* g_instance;
94 77
95 static const char kVrShellUIURL[] = "chrome://vr-shell-ui"; 78 static const char kVrShellUIURL[] = "chrome://vr-shell-ui";
96 79
97 float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) { 80 float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) {
98 float xdiff = (vec1.x - vec2.x); 81 float xdiff = (vec1.x - vec2.x);
99 float ydiff = (vec1.y - vec2.y); 82 float ydiff = (vec1.y - vec2.y);
100 float zdiff = (vec1.z - vec2.z); 83 float zdiff = (vec1.z - vec2.z);
101 float scale = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff; 84 float scale = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff;
102 return std::sqrt(scale); 85 return std::sqrt(scale);
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 // The head pose has redundant data. Assume we're only using the 397 // The head pose has redundant data. Assume we're only using the
415 // object_from_reference_matrix, we're not updating position_external. 398 // object_from_reference_matrix, we're not updating position_external.
416 // TODO: Not sure what object_from_reference_matrix is. The new api removed 399 // TODO: Not sure what object_from_reference_matrix is. The new api removed
417 // it. For now, removing it seems working fine. 400 // it. For now, removing it seems working fine.
418 gvr_api_->ApplyNeckModel(head_pose, 1.0f); 401 gvr_api_->ApplyNeckModel(head_pose, 1.0f);
419 } 402 }
420 403
421 // Bind back to the default framebuffer. 404 // Bind back to the default framebuffer.
422 frame.BindBuffer(0); 405 frame.BindBuffer(0);
423 406
407 HandleQueuedTasks();
408
409 // Update the render position of all UI elements (including desktop).
410 float screen_tilt = desktop_screen_tilt_ * M_PI / 180.0f;
411 scene_->UpdateTransforms(screen_tilt, UiScene::TimeInMicroseconds());
412
424 if (webvr_mode_) { 413 if (webvr_mode_) {
425 DrawWebVr(); 414 DrawWebVr();
426 if (!webvr_secure_origin_) {
427 DrawWebVrOverlay(target_time.monotonic_system_time_nanos);
428 }
429
430 // When using async reprojection, we need to know which pose was used in 415 // 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 416 // the WebVR app for drawing this frame. Due to unknown amounts of
432 // buffering in the compositor and SurfaceTexture, we read the pose number 417 // 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 418 // 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 419 // 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 420 // pixels is an expensive operation. TODO(klausw): stop doing this once we
436 // have working no-compositor rendering for WebVR. 421 // have working no-compositor rendering for WebVR.
437 if (gvr_api_->GetAsyncReprojectionEnabled()) { 422 if (gvr_api_->GetAsyncReprojectionEnabled()) {
438 uint32_t webvr_pose_frame = GetPixelEncodedPoseIndex(); 423 uint32_t webvr_pose_frame = GetPixelEncodedPoseIndex();
439 head_pose = webvr_head_pose_[webvr_pose_frame % kPoseRingBufferSize]; 424 head_pose = webvr_head_pose_[webvr_pose_frame % kPoseRingBufferSize];
440 } 425 }
441 } else { 426 } else {
442 DrawVrShell(head_pose); 427 UpdateController(GetForwardVector(head_pose));
443 } 428 }
444 429
430 DrawVrShell(head_pose);
431
445 frame.Unbind(); 432 frame.Unbind();
446 frame.Submit(*buffer_viewport_list_, head_pose); 433 frame.Submit(*buffer_viewport_list_, head_pose);
447 } 434 }
448 435
449 void VrShell::DrawVrShell(const gvr::Mat4f& head_pose) { 436 void VrShell::DrawVrShell(const gvr::Mat4f& head_pose) {
450 float screen_tilt = desktop_screen_tilt_ * M_PI / 180.0f; 437 if (!webvr_mode_) {
451 438 glEnable(GL_CULL_FACE);
452 HandleQueuedTasks(); 439 glEnable(GL_DEPTH_TEST);
453 440 glEnable(GL_SCISSOR_TEST);
454 // Update the render position of all UI elements (including desktop). 441 glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
455 scene_->UpdateTransforms(screen_tilt, UiScene::TimeInMicroseconds()); 442 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
456 443 }
457 UpdateController(GetForwardVector(head_pose));
458
459 // Use culling to remove back faces.
460 glEnable(GL_CULL_FACE);
461
462 // Enable depth testing.
463 glEnable(GL_DEPTH_TEST);
464 glEnable(GL_SCISSOR_TEST);
465
466 glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
467 444
468 buffer_viewport_list_->GetBufferViewport(GVR_LEFT_EYE, 445 buffer_viewport_list_->GetBufferViewport(GVR_LEFT_EYE,
469 buffer_viewport_.get()); 446 buffer_viewport_.get());
470 DrawEye(GVR_LEFT_EYE, head_pose, *buffer_viewport_); 447 DrawEye(GVR_LEFT_EYE, head_pose, *buffer_viewport_);
471 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE, 448 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE,
472 buffer_viewport_.get()); 449 buffer_viewport_.get());
473 DrawEye(GVR_RIGHT_EYE, head_pose, *buffer_viewport_); 450 DrawEye(GVR_RIGHT_EYE, head_pose, *buffer_viewport_);
474 } 451 }
475 452
476 void VrShell::DrawEye(gvr::Eye eye, 453 void VrShell::DrawEye(gvr::Eye eye,
(...skipping 15 matching lines...) Expand all
492 PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar), 469 PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar),
493 eye_matrix); 470 eye_matrix);
494 const gvr::Mat4f world_render_matrix = MatrixMul( 471 const gvr::Mat4f world_render_matrix = MatrixMul(
495 PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar), 472 PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar),
496 head_matrix); 473 head_matrix);
497 474
498 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 475 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
499 476
500 // TODO(mthiesse): Draw order for transparency. 477 // TODO(mthiesse): Draw order for transparency.
501 DrawUI(world_render_matrix, fov_render_matrix); 478 DrawUI(world_render_matrix, fov_render_matrix);
502 DrawCursor(world_render_matrix); 479 if (!webvr_mode_) {
503 } 480 DrawCursor(world_render_matrix);
504 481 }
505 bool VrShell::IsUiTextureReady() {
506 return ui_tex_width_ > 0 && ui_tex_height_ > 0;
507 }
508
509 Rectf VrShell::MakeUiGlCopyRect(Recti pixel_rect) {
510 CHECK(IsUiTextureReady());
511 return Rectf({
512 static_cast<float>(pixel_rect.x) / ui_tex_width_,
513 static_cast<float>(pixel_rect.y) / ui_tex_height_,
514 static_cast<float>(pixel_rect.width) / ui_tex_width_,
515 static_cast<float>(pixel_rect.height) / ui_tex_height_});
516 } 482 }
517 483
518 void VrShell::DrawUI(const gvr::Mat4f& world_matrix, 484 void VrShell::DrawUI(const gvr::Mat4f& world_matrix,
519 const gvr::Mat4f& fov_matrix) { 485 const gvr::Mat4f& fov_matrix) {
520 for (const auto& rect : scene_->GetUiElements()) { 486 for (const auto& rect : scene_->GetUiElements()) {
521 if (!rect->visible) { 487 if (!rect->visible) {
522 continue; 488 continue;
523 } 489 }
490 if (webvr_mode_ && rect->id == kBrowserUiElementId) {
mthiesse 2016/10/21 14:14:50 Technically we could still control this through ja
cjgrant 2016/10/24 20:00:18 This decoupling is a bit involved, and hence is up
491 continue;
492 }
524 493
525 Rectf copy_rect; 494 Rectf copy_rect;
526 jint texture_handle; 495 jint texture_handle;
527 if (rect->id == kBrowserUiElementId) { 496 if (rect->id == kBrowserUiElementId) {
528 copy_rect = {0, 0, 1, 1}; 497 copy_rect = {0, 0, 1, 1};
529 texture_handle = content_texture_id_; 498 texture_handle = content_texture_id_;
530 } else { 499 } else {
531 copy_rect.x = static_cast<float>(rect->copy_rect.x) / ui_tex_width_; 500 copy_rect.x = static_cast<float>(rect->copy_rect.x) / ui_tex_width_;
532 copy_rect.y = static_cast<float>(rect->copy_rect.y) / ui_tex_height_; 501 copy_rect.y = static_cast<float>(rect->copy_rect.y) / ui_tex_height_;
533 copy_rect.width = static_cast<float>(rect->copy_rect.width) / 502 copy_rect.width = static_cast<float>(rect->copy_rect.width) /
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 glDisable(GL_BLEND); 597 glDisable(GL_BLEND);
629 glDisable(GL_POLYGON_OFFSET_FILL); 598 glDisable(GL_POLYGON_OFFSET_FILL);
630 599
631 // Don't need to clear, since we're drawing over the entire render target. 600 // Don't need to clear, since we're drawing over the entire render target.
632 glClear(GL_COLOR_BUFFER_BIT); 601 glClear(GL_COLOR_BUFFER_BIT);
633 602
634 glViewport(0, 0, render_size_.width, render_size_.height); 603 glViewport(0, 0, render_size_.width, render_size_.height);
635 vr_shell_renderer_->GetWebVrRenderer()->Draw(content_texture_id_); 604 vr_shell_renderer_->GetWebVrRenderer()->Draw(content_texture_id_);
636 } 605 }
637 606
638 void VrShell::DrawWebVrOverlay(int64_t present_time_nanos) {
639 // 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
641 // eye-relative position so that they follow along with head rotations.
642
643 gvr::Mat4f left_eye_view_matrix =
644 gvr_api_->GetEyeFromHeadMatrix(GVR_LEFT_EYE);
645 gvr::Mat4f right_eye_view_matrix =
646 gvr_api_->GetEyeFromHeadMatrix(GVR_RIGHT_EYE);
647
648 buffer_viewport_list_->GetBufferViewport(GVR_LEFT_EYE,
649 buffer_viewport_.get());
650 DrawWebVrEye(left_eye_view_matrix, *buffer_viewport_, present_time_nanos);
651 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE,
652 buffer_viewport_.get());
653 DrawWebVrEye(right_eye_view_matrix, *buffer_viewport_, present_time_nanos);
654 }
655
656 void VrShell::DrawWebVrEye(const gvr::Mat4f& view_matrix,
657 const gvr::BufferViewport& params,
658 int64_t present_time_nanos) {
659 gvr::Recti pixel_rect =
660 CalculatePixelSpaceRect(render_size_, params.GetSourceUv());
661 glViewport(pixel_rect.left, pixel_rect.bottom,
662 pixel_rect.right - pixel_rect.left,
663 pixel_rect.top - pixel_rect.bottom);
664 glScissor(pixel_rect.left, pixel_rect.bottom,
665 pixel_rect.right - pixel_rect.left,
666 pixel_rect.top - pixel_rect.bottom);
667
668 gvr::Mat4f projection_matrix =
669 PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar);
670
671 if (!IsUiTextureReady()) {
672 // If the UI texture hasn't been initialized yet, we can't draw the overlay.
673 return;
674 }
675
676 // Show IDS_WEBSITE_SETTINGS_INSECURE_WEBVR_CONTENT_PERMANENT text.
677 gvr::Mat4f icon_pos;
678 SetIdentityM(icon_pos);
679 // The UI is designed in pixels with the assumption that 1px = 1mm at 1m
680 // distance. Scale mm-to-m and adjust to keep the same angular size if the
681 // distance changes.
682 const float small_icon_width =
683 kWebVrWarningPermanentRect.width / 1000.f * kWebVrWarningDistance;
684 const float small_icon_height =
685 kWebVrWarningPermanentRect.height / 1000.f * kWebVrWarningDistance;
686 const float small_icon_angle =
687 kWebVrWarningPermanentAngle * M_PI / 180.f; // Degrees to radians.
688 ScaleM(icon_pos, icon_pos, small_icon_width, small_icon_height, 1.0f);
689 TranslateM(icon_pos, icon_pos, 0.0f, 0.0f, -kWebVrWarningDistance);
690 icon_pos = MatrixMul(
691 QuatToMatrix(QuatFromAxisAngle({1.f, 0.f, 0.f}, small_icon_angle)),
692 icon_pos);
693 gvr::Mat4f combined = MatrixMul(projection_matrix,
694 MatrixMul(view_matrix, icon_pos));
695 vr_shell_renderer_->GetTexturedQuadRenderer()->Draw(
696 ui_texture_id_, combined, MakeUiGlCopyRect(kWebVrWarningPermanentRect));
697
698 // Check if we also need to show the transient warning.
699 if (present_time_nanos > webvr_warning_end_nanos_) {
700 return;
701 }
702
703 // Show IDS_WEBSITE_SETTINGS_INSECURE_WEBVR_CONTENT_TRANSIENT text.
704 SetIdentityM(icon_pos);
705 const float large_icon_width =
706 kWebVrWarningTransientRect.width / 1000.f * kWebVrWarningDistance;
707 const float large_icon_height =
708 kWebVrWarningTransientRect.height / 1000.f * kWebVrWarningDistance;
709 ScaleM(icon_pos, icon_pos, large_icon_width, large_icon_height, 1.0f);
710 TranslateM(icon_pos, icon_pos, 0.0f, 0.0f, -kWebVrWarningDistance);
711 combined = MatrixMul(projection_matrix,
712 MatrixMul(view_matrix, icon_pos));
713 vr_shell_renderer_->GetTexturedQuadRenderer()->Draw(
714 ui_texture_id_, combined, MakeUiGlCopyRect(kWebVrWarningTransientRect));
715
716 }
717
718 void VrShell::OnTriggerEvent(JNIEnv* env, const JavaParamRef<jobject>& obj) { 607 void VrShell::OnTriggerEvent(JNIEnv* env, const JavaParamRef<jobject>& obj) {
719 // Set a flag to handle this on the render thread at the next frame. 608 // Set a flag to handle this on the render thread at the next frame.
720 touch_pending_ = true; 609 touch_pending_ = true;
721 } 610 }
722 611
723 void VrShell::OnPause(JNIEnv* env, const JavaParamRef<jobject>& obj) { 612 void VrShell::OnPause(JNIEnv* env, const JavaParamRef<jobject>& obj) {
724 if (gvr_api_ == nullptr) 613 if (gvr_api_ == nullptr)
725 return; 614 return;
726 controller_->OnPause(); 615 controller_->OnPause();
727 gvr_api_->PauseTracking(); 616 gvr_api_->PauseTracking();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 constexpr int64_t seconds_to_nanos = 1000 * 1000 * 1000; 656 constexpr int64_t seconds_to_nanos = 1000 * 1000 * 1000;
768 webvr_warning_end_nanos_ = now + kWebVrWarningSeconds * seconds_to_nanos; 657 webvr_warning_end_nanos_ = now + kWebVrWarningSeconds * seconds_to_nanos;
769 html_interface_->SetMode(UiInterface::Mode::WEB_VR); 658 html_interface_->SetMode(UiInterface::Mode::WEB_VR);
770 } else { 659 } else {
771 webvr_warning_end_nanos_ = 0; 660 webvr_warning_end_nanos_ = 0;
772 html_interface_->SetMode(UiInterface::Mode::STANDARD); 661 html_interface_->SetMode(UiInterface::Mode::STANDARD);
773 } 662 }
774 } 663 }
775 664
776 void VrShell::SetWebVRSecureOrigin(bool secure_origin) { 665 void VrShell::SetWebVRSecureOrigin(bool secure_origin) {
777 webvr_secure_origin_ = secure_origin; 666 html_interface_->SetSecureOrigin(secure_origin);
778 } 667 }
779 668
780 void VrShell::SubmitWebVRFrame() { 669 void VrShell::SubmitWebVRFrame() {
781 } 670 }
782 671
783 void VrShell::UpdateWebVRTextureBounds( 672 void VrShell::UpdateWebVRTextureBounds(
784 int eye, float left, float top, float width, float height) { 673 int eye, float left, float top, float width, float height) {
785 gvr::Rectf bounds = { left, top, width, height }; 674 gvr::Rectf bounds = { left, top, width, height };
786 vr_shell_renderer_->GetWebVrRenderer()->UpdateTextureBounds(eye, bounds); 675 vr_shell_renderer_->GetWebVrRenderer()->UpdateTextureBounds(eye, bounds);
787 } 676 }
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
880 const JavaParamRef<jobject>& ui_web_contents, 769 const JavaParamRef<jobject>& ui_web_contents,
881 jlong ui_window_android) { 770 jlong ui_window_android) {
882 return reinterpret_cast<intptr_t>(new VrShell( 771 return reinterpret_cast<intptr_t>(new VrShell(
883 env, obj, content::WebContents::FromJavaWebContents(content_web_contents), 772 env, obj, content::WebContents::FromJavaWebContents(content_web_contents),
884 reinterpret_cast<ui::WindowAndroid*>(content_window_android), 773 reinterpret_cast<ui::WindowAndroid*>(content_window_android),
885 content::WebContents::FromJavaWebContents(ui_web_contents), 774 content::WebContents::FromJavaWebContents(ui_web_contents),
886 reinterpret_cast<ui::WindowAndroid*>(ui_window_android))); 775 reinterpret_cast<ui::WindowAndroid*>(ui_window_android)));
887 } 776 }
888 777
889 } // namespace vr_shell 778 } // namespace vr_shell
OLDNEW
« no previous file with comments | « 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