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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 // TODO(mthiesse): Handedness options. | 60 // TODO(mthiesse): Handedness options. |
61 static constexpr gvr::Vec3f kHandPosition = {0.2f, -0.5f, -0.2f}; | 61 static constexpr gvr::Vec3f kHandPosition = {0.2f, -0.5f, -0.2f}; |
62 | 62 |
63 // Fraction of the z-distance to the object the cursor is drawn at to avoid | 63 // Fraction of the z-distance to the object the cursor is drawn at to avoid |
64 // rounding errors drawing the cursor behind the object. | 64 // rounding errors drawing the cursor behind the object. |
65 static constexpr float kReticleZOffset = 0.99f; | 65 static constexpr float kReticleZOffset = 0.99f; |
66 | 66 |
67 // UI element 0 is the browser content rectangle. | 67 // UI element 0 is the browser content rectangle. |
68 static constexpr int kBrowserUiElementId = 0; | 68 static constexpr int kBrowserUiElementId = 0; |
69 | 69 |
| 70 // Positions and sizes of statically placed UI elements in the UI texture. |
| 71 // TODO(klausw): replace the hardcoded positions with JS position/offset |
| 72 // retrieval once the infrastructure for that is hooked up. |
| 73 static constexpr vr_shell::Recti kWebVrWarningTransientRect = { |
| 74 0, 128, 512, 256}; |
| 75 static constexpr vr_shell::Recti kWebVrWarningPermanentRect = {0, 0, 512, 128}; |
| 76 |
70 vr_shell::VrShell* g_instance; | 77 vr_shell::VrShell* g_instance; |
71 | 78 |
72 static const char kVrShellUIURL[] = "chrome://vr-shell-ui"; | 79 static const char kVrShellUIURL[] = "chrome://vr-shell-ui"; |
73 | 80 |
74 } // namespace | 81 } // namespace |
75 | 82 |
76 namespace vr_shell { | 83 namespace vr_shell { |
77 | 84 |
78 VrShell::VrShell(JNIEnv* env, | 85 VrShell::VrShell(JNIEnv* env, |
79 jobject obj, | 86 jobject obj, |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 gvr::Frame frame = swap_chain_->AcquireFrame(); | 274 gvr::Frame frame = swap_chain_->AcquireFrame(); |
268 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); | 275 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); |
269 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; | 276 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; |
270 head_pose_ = gvr_api_->GetHeadPoseInStartSpace(target_time); | 277 head_pose_ = gvr_api_->GetHeadPoseInStartSpace(target_time); |
271 | 278 |
272 // Bind back to the default framebuffer. | 279 // Bind back to the default framebuffer. |
273 frame.BindBuffer(0); | 280 frame.BindBuffer(0); |
274 | 281 |
275 if (webvr_mode_) { | 282 if (webvr_mode_) { |
276 DrawWebVr(); | 283 DrawWebVr(); |
| 284 if (!webvr_secure_origin_) { |
| 285 DrawWebVrOverlay(target_time.monotonic_system_time_nanos); |
| 286 } |
277 } else { | 287 } else { |
278 DrawVrShell(); | 288 DrawVrShell(); |
279 } | 289 } |
280 | 290 |
281 frame.Unbind(); | 291 frame.Unbind(); |
282 frame.Submit(*buffer_viewport_list_, head_pose_); | 292 frame.Submit(*buffer_viewport_list_, head_pose_); |
283 } | 293 } |
284 | 294 |
285 void VrShell::DrawVrShell() { | 295 void VrShell::DrawVrShell() { |
286 float screen_tilt = desktop_screen_tilt_ * M_PI / 180.0f; | 296 float screen_tilt = desktop_screen_tilt_ * M_PI / 180.0f; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
345 projection_matrix_ = | 355 projection_matrix_ = |
346 PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar); | 356 PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar); |
347 | 357 |
348 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | 358 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
349 | 359 |
350 // TODO(mthiesse): Draw order for transparency. | 360 // TODO(mthiesse): Draw order for transparency. |
351 DrawUI(); | 361 DrawUI(); |
352 DrawCursor(); | 362 DrawCursor(); |
353 } | 363 } |
354 | 364 |
| 365 bool VrShell::IsUiTextureReady() { |
| 366 return ui_tex_width_ > 0 && ui_tex_height_ > 0; |
| 367 } |
| 368 |
| 369 /** |
| 370 * Converts a pixel rectangle to (0..1) float texture coordinates. |
| 371 * |
| 372 * Callers need to ensure that the texture width/height is initialized |
| 373 * by checking IsUiTextureReady() first. |
| 374 */ |
| 375 Rectf VrShell::MakeUiGlCopyRect(Recti pixel_rect) { |
| 376 DCHECK(IsUiTextureReady()); |
| 377 return Rectf({ |
| 378 static_cast<float>(pixel_rect.x) / ui_tex_width_, |
| 379 static_cast<float>(pixel_rect.y) / ui_tex_height_, |
| 380 static_cast<float>(pixel_rect.width) / ui_tex_width_, |
| 381 static_cast<float>(pixel_rect.height) / ui_tex_height_}); |
| 382 } |
| 383 |
355 void VrShell::DrawUI() { | 384 void VrShell::DrawUI() { |
356 for (const auto& rect : scene_.GetUiElements()) { | 385 for (const auto& rect : scene_.GetUiElements()) { |
357 if (!rect->visible) { | 386 if (!rect->visible) { |
358 continue; | 387 continue; |
359 } | 388 } |
360 | 389 |
361 gvr::Mat4f combined_matrix = MatrixMul(view_matrix_, | 390 gvr::Mat4f combined_matrix = MatrixMul(view_matrix_, |
362 rect->transform.to_world); | 391 rect->transform.to_world); |
363 combined_matrix = MatrixMul(projection_matrix_, combined_matrix); | 392 combined_matrix = MatrixMul(projection_matrix_, combined_matrix); |
364 | 393 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 glDepthMask(GL_FALSE); | 467 glDepthMask(GL_FALSE); |
439 glDisable(GL_DEPTH_TEST); | 468 glDisable(GL_DEPTH_TEST); |
440 glDisable(GL_SCISSOR_TEST); | 469 glDisable(GL_SCISSOR_TEST); |
441 glDisable(GL_BLEND); | 470 glDisable(GL_BLEND); |
442 glDisable(GL_POLYGON_OFFSET_FILL); | 471 glDisable(GL_POLYGON_OFFSET_FILL); |
443 | 472 |
444 // Don't need to clear, since we're drawing over the entire render target. | 473 // Don't need to clear, since we're drawing over the entire render target. |
445 | 474 |
446 glViewport(0, 0, render_size_.width, render_size_.height); | 475 glViewport(0, 0, render_size_.width, render_size_.height); |
447 vr_shell_renderer_->GetWebVrRenderer()->Draw(content_texture_id_); | 476 vr_shell_renderer_->GetWebVrRenderer()->Draw(content_texture_id_); |
| 477 } |
448 | 478 |
449 if (!webvr_secure_origin_) { | 479 void VrShell::DrawWebVrOverlay(int64_t present_time_nanos) { |
450 // TODO(klausw): Draw the insecure origin warning here. | 480 // Draw WebVR security warning overlays for each eye. This uses |
| 481 // the eye-from-head matrices but not the pose, goal is to place |
| 482 // the icons in an eye-relative position so that they follow along |
| 483 // with head rotations. |
| 484 |
| 485 gvr::Mat4f left_eye_view_matrix = |
| 486 gvr_api_->GetEyeFromHeadMatrix(GVR_LEFT_EYE); |
| 487 gvr::Mat4f right_eye_view_matrix = |
| 488 gvr_api_->GetEyeFromHeadMatrix(GVR_RIGHT_EYE); |
| 489 |
| 490 buffer_viewport_list_->GetBufferViewport(GVR_LEFT_EYE, |
| 491 buffer_viewport_.get()); |
| 492 DrawWebVrEye(left_eye_view_matrix, *buffer_viewport_, present_time_nanos); |
| 493 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE, |
| 494 buffer_viewport_.get()); |
| 495 DrawWebVrEye(right_eye_view_matrix, *buffer_viewport_, present_time_nanos); |
| 496 } |
| 497 |
| 498 void VrShell::DrawWebVrEye(const gvr::Mat4f& view_matrix, |
| 499 const gvr::BufferViewport& params, |
| 500 int64_t present_time_nanos) { |
| 501 gvr::Recti pixel_rect = |
| 502 CalculatePixelSpaceRect(render_size_, params.GetSourceUv()); |
| 503 glViewport(pixel_rect.left, pixel_rect.bottom, |
| 504 pixel_rect.right - pixel_rect.left, |
| 505 pixel_rect.top - pixel_rect.bottom); |
| 506 glScissor(pixel_rect.left, pixel_rect.bottom, |
| 507 pixel_rect.right - pixel_rect.left, |
| 508 pixel_rect.top - pixel_rect.bottom); |
| 509 |
| 510 gvr::Mat4f projection_matrix = |
| 511 PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar); |
| 512 |
| 513 if (!IsUiTextureReady()) { |
| 514 // If the UI texture hasn't been initialized yet, we can't draw the overlay. |
| 515 return; |
451 } | 516 } |
| 517 |
| 518 // Draw insecure content warning icons. |
| 519 const float warning_depth = 0.7f; // Distance in meters. |
| 520 |
| 521 // Show IDS_WEBSITE_SETTINGS_INSECURE_WEBVR_CONTENT_PERMANENT text. |
| 522 gvr::Mat4f icon_pos; |
| 523 SetIdentityM(icon_pos); |
| 524 const float small_icon_width = 2 * 0.30f * warning_depth; |
| 525 const float small_icon_height = small_icon_width / 4.0f; // 4:1 aspect. |
| 526 const float small_icon_angle = 20.0f * M_PI / 180.f; // Degrees to radians. |
| 527 ScaleM(icon_pos, icon_pos, small_icon_width, small_icon_height, 1.0f); |
| 528 TranslateM(icon_pos, icon_pos, 0.0f, 0.0f, -warning_depth); |
| 529 icon_pos = MatrixMul( |
| 530 QuatToMatrix(QuatFromAxisAngle(1.f, 0.f, 0.f, small_icon_angle)), |
| 531 icon_pos); |
| 532 gvr::Mat4f combined = MatrixMul(projection_matrix, |
| 533 MatrixMul(view_matrix, icon_pos)); |
| 534 vr_shell_renderer_->GetTexturedQuadRenderer()->Draw( |
| 535 ui_texture_id_, combined, MakeUiGlCopyRect(kWebVrWarningPermanentRect)); |
| 536 |
| 537 // Check if we also need to show the transient warning. |
| 538 if (present_time_nanos > webvr_warning_end_nanos_) { |
| 539 return; |
| 540 } |
| 541 |
| 542 // Show IDS_WEBSITE_SETTINGS_INSECURE_WEBVR_CONTENT_TRANSIENT text. |
| 543 SetIdentityM(icon_pos); |
| 544 const float large_icon_width = 2 * 0.25f * warning_depth; |
| 545 const float large_icon_height = large_icon_width / 2.0f; // 2:1 aspect. |
| 546 ScaleM(icon_pos, icon_pos, large_icon_width, large_icon_height, 1.0f); |
| 547 TranslateM(icon_pos, icon_pos, 0.0f, 0.0f, -warning_depth); |
| 548 combined = MatrixMul(projection_matrix, |
| 549 MatrixMul(view_matrix, icon_pos)); |
| 550 vr_shell_renderer_->GetTexturedQuadRenderer()->Draw( |
| 551 ui_texture_id_, combined, MakeUiGlCopyRect(kWebVrWarningTransientRect)); |
| 552 |
452 } | 553 } |
453 | 554 |
454 void VrShell::OnPause(JNIEnv* env, const JavaParamRef<jobject>& obj) { | 555 void VrShell::OnPause(JNIEnv* env, const JavaParamRef<jobject>& obj) { |
455 if (gvr_api_ == nullptr) | 556 if (gvr_api_ == nullptr) |
456 return; | 557 return; |
457 gvr_api_->PauseTracking(); | 558 gvr_api_->PauseTracking(); |
458 } | 559 } |
459 | 560 |
460 void VrShell::OnResume(JNIEnv* env, const JavaParamRef<jobject>& obj) { | 561 void VrShell::OnResume(JNIEnv* env, const JavaParamRef<jobject>& obj) { |
461 if (gvr_api_ == nullptr) | 562 if (gvr_api_ == nullptr) |
(...skipping 18 matching lines...) Expand all Loading... |
480 // TODO(bshe): ui_text_width_ and ui_tex_height_ should be only used on render | 581 // TODO(bshe): ui_text_width_ and ui_tex_height_ should be only used on render |
481 // thread. | 582 // thread. |
482 ui_tex_width_ = width; | 583 ui_tex_width_ = width; |
483 ui_tex_height_ = height; | 584 ui_tex_height_ = height; |
484 } | 585 } |
485 | 586 |
486 void VrShell::SetWebVrMode(JNIEnv* env, | 587 void VrShell::SetWebVrMode(JNIEnv* env, |
487 const base::android::JavaParamRef<jobject>& obj, | 588 const base::android::JavaParamRef<jobject>& obj, |
488 bool enabled) { | 589 bool enabled) { |
489 webvr_mode_ = enabled; | 590 webvr_mode_ = enabled; |
| 591 if (enabled) { |
| 592 const int64_t warning_seconds = 30; |
| 593 int64_t now = gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos; |
| 594 webvr_warning_end_nanos_ = now + warning_seconds * 1000 * 1000 * 1000; |
| 595 } else { |
| 596 webvr_warning_end_nanos_ = 0; |
| 597 } |
490 } | 598 } |
491 | 599 |
492 void VrShell::SetWebVRSecureOrigin(bool secure_origin) { | 600 void VrShell::SetWebVRSecureOrigin(bool secure_origin) { |
493 webvr_secure_origin_ = secure_origin; | 601 webvr_secure_origin_ = secure_origin; |
494 } | 602 } |
495 | 603 |
496 void VrShell::SubmitWebVRFrame() { | 604 void VrShell::SubmitWebVRFrame() { |
497 } | 605 } |
498 | 606 |
499 void VrShell::UpdateWebVRTextureBounds( | 607 void VrShell::UpdateWebVRTextureBounds( |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
562 content::WebContents::FromJavaWebContents(content_web_contents)); | 670 content::WebContents::FromJavaWebContents(content_web_contents)); |
563 content::ContentViewCore* ui_core = content::ContentViewCore::FromWebContents( | 671 content::ContentViewCore* ui_core = content::ContentViewCore::FromWebContents( |
564 content::WebContents::FromJavaWebContents(ui_web_contents)); | 672 content::WebContents::FromJavaWebContents(ui_web_contents)); |
565 return reinterpret_cast<intptr_t>(new VrShell( | 673 return reinterpret_cast<intptr_t>(new VrShell( |
566 env, obj, c_core, | 674 env, obj, c_core, |
567 reinterpret_cast<ui::WindowAndroid*>(content_window_android), ui_core, | 675 reinterpret_cast<ui::WindowAndroid*>(content_window_android), ui_core, |
568 reinterpret_cast<ui::WindowAndroid*>(ui_window_android))); | 676 reinterpret_cast<ui::WindowAndroid*>(ui_window_android))); |
569 } | 677 } |
570 | 678 |
571 } // namespace vr_shell | 679 } // namespace vr_shell |
OLD | NEW |