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 <thread> | 7 #include <thread> |
8 | 8 |
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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 static constexpr float kReticleOffset = 0.99f; | 65 static constexpr float kReticleOffset = 0.99f; |
66 | 66 |
67 // Limit the rendering distance of the reticle to the distance to a corner of | 67 // Limit the rendering distance of the reticle to the distance to a corner of |
68 // the content quad, times this value. This lets the rendering distance | 68 // the content quad, times this value. This lets the rendering distance |
69 // adjust according to content quad placement. | 69 // adjust according to content quad placement. |
70 static constexpr float kReticleDistanceMultiplier = 1.5f; | 70 static constexpr float kReticleDistanceMultiplier = 1.5f; |
71 | 71 |
72 // UI element 0 is the browser content rectangle. | 72 // UI element 0 is the browser content rectangle. |
73 static constexpr int kBrowserUiElementId = 0; | 73 static constexpr int kBrowserUiElementId = 0; |
74 | 74 |
| 75 // Positions and sizes of statically placed UI elements in the UI texture. |
| 76 // TODO(klausw): replace the hardcoded positions with JS position/offset |
| 77 // retrieval once the infrastructure for that is hooked up. |
| 78 // |
| 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. |
| 81 // The warning overlays should be fairly close since they cut holes |
| 82 // into geometry (they ignore the Z buffer), leading to odd effects |
| 83 // if they are far away. |
| 84 static constexpr vr_shell::Recti kWebVrWarningTransientRect = { |
| 85 0, 128, 512, 256}; |
| 86 static constexpr vr_shell::Recti kWebVrWarningPermanentRect = {0, 0, 512, 128}; |
| 87 static constexpr float kWebVrWarningDistance = 0.7f; // meters |
| 88 static constexpr float kWebVrWarningPermanentAngle = 16.3f; // degrees up |
| 89 // How long the transient warning needs to be displayed. |
| 90 static constexpr int64_t kWebVrWarningSeconds = 30; |
| 91 |
75 vr_shell::VrShell* g_instance; | 92 vr_shell::VrShell* g_instance; |
76 | 93 |
77 static const char kVrShellUIURL[] = "chrome://vr-shell-ui"; | 94 static const char kVrShellUIURL[] = "chrome://vr-shell-ui"; |
78 | 95 |
79 float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) { | 96 float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) { |
80 float xdiff = (vec1.x - vec2.x); | 97 float xdiff = (vec1.x - vec2.x); |
81 float ydiff = (vec1.y - vec2.y); | 98 float ydiff = (vec1.y - vec2.y); |
82 float zdiff = (vec1.z - vec2.z); | 99 float zdiff = (vec1.z - vec2.z); |
83 float scale = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff; | 100 float scale = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff; |
84 return std::sqrt(scale); | 101 return std::sqrt(scale); |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 // TODO: Not sure what object_from_reference_matrix is. The new api removed | 319 // TODO: Not sure what object_from_reference_matrix is. The new api removed |
303 // it. For now, removing it seems working fine. | 320 // it. For now, removing it seems working fine. |
304 ApplyNeckModel(head_pose); | 321 ApplyNeckModel(head_pose); |
305 } | 322 } |
306 | 323 |
307 // Bind back to the default framebuffer. | 324 // Bind back to the default framebuffer. |
308 frame.BindBuffer(0); | 325 frame.BindBuffer(0); |
309 | 326 |
310 if (webvr_mode_) { | 327 if (webvr_mode_) { |
311 DrawWebVr(); | 328 DrawWebVr(); |
| 329 if (!webvr_secure_origin_) { |
| 330 DrawWebVrOverlay(target_time.monotonic_system_time_nanos); |
| 331 } |
312 } else { | 332 } else { |
313 DrawVrShell(head_pose); | 333 DrawVrShell(head_pose); |
314 } | 334 } |
315 | 335 |
316 frame.Unbind(); | 336 frame.Unbind(); |
317 frame.Submit(*buffer_viewport_list_, head_pose); | 337 frame.Submit(*buffer_viewport_list_, head_pose); |
318 } | 338 } |
319 | 339 |
320 void VrShell::DrawVrShell(const gvr::Mat4f& head_pose) { | 340 void VrShell::DrawVrShell(const gvr::Mat4f& head_pose) { |
321 float screen_tilt = desktop_screen_tilt_ * M_PI / 180.0f; | 341 float screen_tilt = desktop_screen_tilt_ * M_PI / 180.0f; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar), | 385 PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar), |
366 view_matrix); | 386 view_matrix); |
367 | 387 |
368 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | 388 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
369 | 389 |
370 // TODO(mthiesse): Draw order for transparency. | 390 // TODO(mthiesse): Draw order for transparency. |
371 DrawUI(render_matrix); | 391 DrawUI(render_matrix); |
372 DrawCursor(render_matrix); | 392 DrawCursor(render_matrix); |
373 } | 393 } |
374 | 394 |
| 395 bool VrShell::IsUiTextureReady() { |
| 396 return ui_tex_width_ > 0 && ui_tex_height_ > 0; |
| 397 } |
| 398 |
| 399 Rectf VrShell::MakeUiGlCopyRect(Recti pixel_rect) { |
| 400 DCHECK(IsUiTextureReady()); |
| 401 return Rectf({ |
| 402 static_cast<float>(pixel_rect.x) / ui_tex_width_, |
| 403 static_cast<float>(pixel_rect.y) / ui_tex_height_, |
| 404 static_cast<float>(pixel_rect.width) / ui_tex_width_, |
| 405 static_cast<float>(pixel_rect.height) / ui_tex_height_}); |
| 406 } |
| 407 |
375 void VrShell::DrawUI(const gvr::Mat4f& render_matrix) { | 408 void VrShell::DrawUI(const gvr::Mat4f& render_matrix) { |
376 for (const auto& rect : scene_.GetUiElements()) { | 409 for (const auto& rect : scene_.GetUiElements()) { |
377 if (!rect->visible) { | 410 if (!rect->visible) { |
378 continue; | 411 continue; |
379 } | 412 } |
380 | 413 |
381 Rectf copy_rect; | 414 Rectf copy_rect; |
382 jint texture_handle; | 415 jint texture_handle; |
383 if (rect->id == kBrowserUiElementId) { | 416 if (rect->id == kBrowserUiElementId) { |
384 copy_rect = {0, 0, 1, 1}; | 417 copy_rect = {0, 0, 1, 1}; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 glDepthMask(GL_FALSE); | 494 glDepthMask(GL_FALSE); |
462 glDisable(GL_DEPTH_TEST); | 495 glDisable(GL_DEPTH_TEST); |
463 glDisable(GL_SCISSOR_TEST); | 496 glDisable(GL_SCISSOR_TEST); |
464 glDisable(GL_BLEND); | 497 glDisable(GL_BLEND); |
465 glDisable(GL_POLYGON_OFFSET_FILL); | 498 glDisable(GL_POLYGON_OFFSET_FILL); |
466 | 499 |
467 // Don't need to clear, since we're drawing over the entire render target. | 500 // Don't need to clear, since we're drawing over the entire render target. |
468 | 501 |
469 glViewport(0, 0, render_size_.width, render_size_.height); | 502 glViewport(0, 0, render_size_.width, render_size_.height); |
470 vr_shell_renderer_->GetWebVrRenderer()->Draw(content_texture_id_); | 503 vr_shell_renderer_->GetWebVrRenderer()->Draw(content_texture_id_); |
| 504 } |
471 | 505 |
472 if (!webvr_secure_origin_) { | 506 void VrShell::DrawWebVrOverlay(int64_t present_time_nanos) { |
473 // TODO(klausw): Draw the insecure origin warning here. | 507 // Draw WebVR security warning overlays for each eye. This uses the |
| 508 // eye-from-head matrices but not the pose, goal is to place the icons in an |
| 509 // eye-relative position so that they follow along with head rotations. |
| 510 |
| 511 gvr::Mat4f left_eye_view_matrix = |
| 512 gvr_api_->GetEyeFromHeadMatrix(GVR_LEFT_EYE); |
| 513 gvr::Mat4f right_eye_view_matrix = |
| 514 gvr_api_->GetEyeFromHeadMatrix(GVR_RIGHT_EYE); |
| 515 |
| 516 buffer_viewport_list_->GetBufferViewport(GVR_LEFT_EYE, |
| 517 buffer_viewport_.get()); |
| 518 DrawWebVrEye(left_eye_view_matrix, *buffer_viewport_, present_time_nanos); |
| 519 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE, |
| 520 buffer_viewport_.get()); |
| 521 DrawWebVrEye(right_eye_view_matrix, *buffer_viewport_, present_time_nanos); |
| 522 } |
| 523 |
| 524 void VrShell::DrawWebVrEye(const gvr::Mat4f& view_matrix, |
| 525 const gvr::BufferViewport& params, |
| 526 int64_t present_time_nanos) { |
| 527 gvr::Recti pixel_rect = |
| 528 CalculatePixelSpaceRect(render_size_, params.GetSourceUv()); |
| 529 glViewport(pixel_rect.left, pixel_rect.bottom, |
| 530 pixel_rect.right - pixel_rect.left, |
| 531 pixel_rect.top - pixel_rect.bottom); |
| 532 glScissor(pixel_rect.left, pixel_rect.bottom, |
| 533 pixel_rect.right - pixel_rect.left, |
| 534 pixel_rect.top - pixel_rect.bottom); |
| 535 |
| 536 gvr::Mat4f projection_matrix = |
| 537 PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar); |
| 538 |
| 539 if (!IsUiTextureReady()) { |
| 540 // If the UI texture hasn't been initialized yet, we can't draw the overlay. |
| 541 return; |
474 } | 542 } |
| 543 |
| 544 // Show IDS_WEBSITE_SETTINGS_INSECURE_WEBVR_CONTENT_PERMANENT text. |
| 545 gvr::Mat4f icon_pos; |
| 546 SetIdentityM(icon_pos); |
| 547 const float small_icon_width = |
| 548 kWebVrWarningPermanentRect.width / 1000.f * kWebVrWarningDistance; |
| 549 const float small_icon_height = |
| 550 kWebVrWarningPermanentRect.height / 1000.f * kWebVrWarningDistance; |
| 551 const float small_icon_angle = |
| 552 kWebVrWarningPermanentAngle * M_PI / 180.f; // Degrees to radians. |
| 553 ScaleM(icon_pos, icon_pos, small_icon_width, small_icon_height, 1.0f); |
| 554 TranslateM(icon_pos, icon_pos, 0.0f, 0.0f, -kWebVrWarningDistance); |
| 555 icon_pos = MatrixMul( |
| 556 QuatToMatrix(QuatFromAxisAngle({1.f, 0.f, 0.f}, small_icon_angle)), |
| 557 icon_pos); |
| 558 gvr::Mat4f combined = MatrixMul(projection_matrix, |
| 559 MatrixMul(view_matrix, icon_pos)); |
| 560 vr_shell_renderer_->GetTexturedQuadRenderer()->Draw( |
| 561 ui_texture_id_, combined, MakeUiGlCopyRect(kWebVrWarningPermanentRect)); |
| 562 |
| 563 // Check if we also need to show the transient warning. |
| 564 if (present_time_nanos > webvr_warning_end_nanos_) { |
| 565 return; |
| 566 } |
| 567 |
| 568 // Show IDS_WEBSITE_SETTINGS_INSECURE_WEBVR_CONTENT_TRANSIENT text. |
| 569 SetIdentityM(icon_pos); |
| 570 const float large_icon_width = |
| 571 kWebVrWarningTransientRect.width / 1000.f * kWebVrWarningDistance; |
| 572 const float large_icon_height = |
| 573 kWebVrWarningTransientRect.height / 1000.f * kWebVrWarningDistance; |
| 574 ScaleM(icon_pos, icon_pos, large_icon_width, large_icon_height, 1.0f); |
| 575 TranslateM(icon_pos, icon_pos, 0.0f, 0.0f, -kWebVrWarningDistance); |
| 576 combined = MatrixMul(projection_matrix, |
| 577 MatrixMul(view_matrix, icon_pos)); |
| 578 vr_shell_renderer_->GetTexturedQuadRenderer()->Draw( |
| 579 ui_texture_id_, combined, MakeUiGlCopyRect(kWebVrWarningTransientRect)); |
| 580 |
475 } | 581 } |
476 | 582 |
477 void VrShell::OnPause(JNIEnv* env, const JavaParamRef<jobject>& obj) { | 583 void VrShell::OnPause(JNIEnv* env, const JavaParamRef<jobject>& obj) { |
478 if (gvr_api_ == nullptr) | 584 if (gvr_api_ == nullptr) |
479 return; | 585 return; |
480 gvr_api_->PauseTracking(); | 586 gvr_api_->PauseTracking(); |
481 } | 587 } |
482 | 588 |
483 void VrShell::OnResume(JNIEnv* env, const JavaParamRef<jobject>& obj) { | 589 void VrShell::OnResume(JNIEnv* env, const JavaParamRef<jobject>& obj) { |
484 if (gvr_api_ == nullptr) | 590 if (gvr_api_ == nullptr) |
(...skipping 26 matching lines...) Expand all Loading... |
511 // TODO(bshe): ui_text_width_ and ui_tex_height_ should be only used on render | 617 // TODO(bshe): ui_text_width_ and ui_tex_height_ should be only used on render |
512 // thread. | 618 // thread. |
513 ui_tex_width_ = width; | 619 ui_tex_width_ = width; |
514 ui_tex_height_ = height; | 620 ui_tex_height_ = height; |
515 } | 621 } |
516 | 622 |
517 void VrShell::SetWebVrMode(JNIEnv* env, | 623 void VrShell::SetWebVrMode(JNIEnv* env, |
518 const base::android::JavaParamRef<jobject>& obj, | 624 const base::android::JavaParamRef<jobject>& obj, |
519 bool enabled) { | 625 bool enabled) { |
520 webvr_mode_ = enabled; | 626 webvr_mode_ = enabled; |
| 627 if (enabled) { |
| 628 int64_t now = gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos; |
| 629 constexpr int64_t seconds_to_nanos = 1000 * 1000 * 1000; |
| 630 webvr_warning_end_nanos_ = now + kWebVrWarningSeconds * seconds_to_nanos; |
| 631 } else { |
| 632 webvr_warning_end_nanos_ = 0; |
| 633 } |
521 } | 634 } |
522 | 635 |
523 void VrShell::SetWebVRSecureOrigin(bool secure_origin) { | 636 void VrShell::SetWebVRSecureOrigin(bool secure_origin) { |
524 webvr_secure_origin_ = secure_origin; | 637 webvr_secure_origin_ = secure_origin; |
525 } | 638 } |
526 | 639 |
527 void VrShell::SubmitWebVRFrame() { | 640 void VrShell::SubmitWebVRFrame() { |
528 } | 641 } |
529 | 642 |
530 void VrShell::UpdateWebVRTextureBounds( | 643 void VrShell::UpdateWebVRTextureBounds( |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
593 content::WebContents::FromJavaWebContents(content_web_contents)); | 706 content::WebContents::FromJavaWebContents(content_web_contents)); |
594 content::ContentViewCore* ui_core = content::ContentViewCore::FromWebContents( | 707 content::ContentViewCore* ui_core = content::ContentViewCore::FromWebContents( |
595 content::WebContents::FromJavaWebContents(ui_web_contents)); | 708 content::WebContents::FromJavaWebContents(ui_web_contents)); |
596 return reinterpret_cast<intptr_t>(new VrShell( | 709 return reinterpret_cast<intptr_t>(new VrShell( |
597 env, obj, c_core, | 710 env, obj, c_core, |
598 reinterpret_cast<ui::WindowAndroid*>(content_window_android), ui_core, | 711 reinterpret_cast<ui::WindowAndroid*>(content_window_android), ui_core, |
599 reinterpret_cast<ui::WindowAndroid*>(ui_window_android))); | 712 reinterpret_cast<ui::WindowAndroid*>(ui_window_android))); |
600 } | 713 } |
601 | 714 |
602 } // namespace vr_shell | 715 } // namespace vr_shell |
OLD | NEW |