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