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 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 // | |
| 74 // UI is designed with 1 pixel = 1mm at 1m distance. It's rescaled to | |
| 75 // maintain the same angular resolution if placed closer or further. | |
| 76 // The warning overlays should be fairly close since they cut holes | |
| 77 // into geometry (they ignore the Z buffer), leading to odd effects | |
| 78 // if they are far away. | |
| 79 static constexpr vr_shell::Recti kWebVrWarningTransientRect = { | |
| 80 0, 128, 512, 256}; | |
| 81 static constexpr vr_shell::Recti kWebVrWarningPermanentRect = {0, 0, 512, 128}; | |
| 82 static constexpr float kWebVrWarningDistance = 0.7f; // meters | |
| 83 static constexpr float kWebVrWarningPermanentAngle = 16.3f; // degrees up | |
| 84 | |
| 70 vr_shell::VrShell* g_instance; | 85 vr_shell::VrShell* g_instance; |
| 71 | 86 |
| 72 static const char kVrShellUIURL[] = "chrome://vr-shell-ui"; | 87 static const char kVrShellUIURL[] = "chrome://vr-shell-ui"; |
| 73 | 88 |
| 74 } // namespace | 89 } // namespace |
| 75 | 90 |
| 76 namespace vr_shell { | 91 namespace vr_shell { |
| 77 | 92 |
| 78 VrShell::VrShell(JNIEnv* env, | 93 VrShell::VrShell(JNIEnv* env, |
| 79 jobject obj, | 94 jobject obj, |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 267 gvr::Frame frame = swap_chain_->AcquireFrame(); | 282 gvr::Frame frame = swap_chain_->AcquireFrame(); |
| 268 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); | 283 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); |
| 269 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; | 284 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; |
| 270 head_pose_ = gvr_api_->GetHeadPoseInStartSpace(target_time); | 285 head_pose_ = gvr_api_->GetHeadPoseInStartSpace(target_time); |
| 271 | 286 |
| 272 // Bind back to the default framebuffer. | 287 // Bind back to the default framebuffer. |
| 273 frame.BindBuffer(0); | 288 frame.BindBuffer(0); |
| 274 | 289 |
| 275 if (webvr_mode_) { | 290 if (webvr_mode_) { |
| 276 DrawWebVr(); | 291 DrawWebVr(); |
| 292 if (!webvr_secure_origin_) { | |
| 293 DrawWebVrOverlay(target_time.monotonic_system_time_nanos); | |
| 294 } | |
| 277 } else { | 295 } else { |
| 278 DrawVrShell(); | 296 DrawVrShell(); |
| 279 } | 297 } |
| 280 | 298 |
| 281 frame.Unbind(); | 299 frame.Unbind(); |
| 282 frame.Submit(*buffer_viewport_list_, head_pose_); | 300 frame.Submit(*buffer_viewport_list_, head_pose_); |
| 283 } | 301 } |
| 284 | 302 |
| 285 void VrShell::DrawVrShell() { | 303 void VrShell::DrawVrShell() { |
| 286 float screen_tilt = desktop_screen_tilt_ * M_PI / 180.0f; | 304 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_ = | 363 projection_matrix_ = |
| 346 PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar); | 364 PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar); |
| 347 | 365 |
| 348 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | 366 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
| 349 | 367 |
| 350 // TODO(mthiesse): Draw order for transparency. | 368 // TODO(mthiesse): Draw order for transparency. |
| 351 DrawUI(); | 369 DrawUI(); |
| 352 DrawCursor(); | 370 DrawCursor(); |
| 353 } | 371 } |
| 354 | 372 |
| 373 bool VrShell::IsUiTextureReady() { | |
| 374 return ui_tex_width_ > 0 && ui_tex_height_ > 0; | |
| 375 } | |
| 376 | |
| 377 /** | |
| 378 * Converts a pixel rectangle to (0..1) float texture coordinates. | |
| 379 * | |
| 380 * Callers need to ensure that the texture width/height is initialized | |
| 381 * by checking IsUiTextureReady() first. | |
| 382 */ | |
|
bshe
2016/09/29 13:50:56
nit: move comment to .h file? Also, this seems lik
| |
| 383 Rectf VrShell::MakeUiGlCopyRect(Recti pixel_rect) { | |
| 384 DCHECK(IsUiTextureReady()); | |
| 385 return Rectf({ | |
| 386 static_cast<float>(pixel_rect.x) / ui_tex_width_, | |
| 387 static_cast<float>(pixel_rect.y) / ui_tex_height_, | |
| 388 static_cast<float>(pixel_rect.width) / ui_tex_width_, | |
| 389 static_cast<float>(pixel_rect.height) / ui_tex_height_}); | |
| 390 } | |
| 391 | |
| 355 void VrShell::DrawUI() { | 392 void VrShell::DrawUI() { |
| 356 for (const auto& rect : scene_.GetUiElements()) { | 393 for (const auto& rect : scene_.GetUiElements()) { |
| 357 if (!rect->visible) { | 394 if (!rect->visible) { |
| 358 continue; | 395 continue; |
| 359 } | 396 } |
| 360 | 397 |
| 361 gvr::Mat4f combined_matrix = MatrixMul(view_matrix_, | 398 gvr::Mat4f combined_matrix = MatrixMul(view_matrix_, |
| 362 rect->transform.to_world); | 399 rect->transform.to_world); |
| 363 combined_matrix = MatrixMul(projection_matrix_, combined_matrix); | 400 combined_matrix = MatrixMul(projection_matrix_, combined_matrix); |
| 364 | 401 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 438 glDepthMask(GL_FALSE); | 475 glDepthMask(GL_FALSE); |
| 439 glDisable(GL_DEPTH_TEST); | 476 glDisable(GL_DEPTH_TEST); |
| 440 glDisable(GL_SCISSOR_TEST); | 477 glDisable(GL_SCISSOR_TEST); |
| 441 glDisable(GL_BLEND); | 478 glDisable(GL_BLEND); |
| 442 glDisable(GL_POLYGON_OFFSET_FILL); | 479 glDisable(GL_POLYGON_OFFSET_FILL); |
| 443 | 480 |
| 444 // Don't need to clear, since we're drawing over the entire render target. | 481 // Don't need to clear, since we're drawing over the entire render target. |
| 445 | 482 |
| 446 glViewport(0, 0, render_size_.width, render_size_.height); | 483 glViewport(0, 0, render_size_.width, render_size_.height); |
| 447 vr_shell_renderer_->GetWebVrRenderer()->Draw(content_texture_id_); | 484 vr_shell_renderer_->GetWebVrRenderer()->Draw(content_texture_id_); |
| 485 } | |
| 448 | 486 |
| 449 if (!webvr_secure_origin_) { | 487 void VrShell::DrawWebVrOverlay(int64_t present_time_nanos) { |
| 450 // TODO(klausw): Draw the insecure origin warning here. | 488 // Draw WebVR security warning overlays for each eye. This uses |
| 489 // the eye-from-head matrices but not the pose, goal is to place | |
| 490 // the icons in an eye-relative position so that they follow along | |
| 491 // with head rotations. | |
|
bshe
2016/09/29 13:50:56
nit: this looks like comment for function. If so,
| |
| 492 | |
| 493 gvr::Mat4f left_eye_view_matrix = | |
| 494 gvr_api_->GetEyeFromHeadMatrix(GVR_LEFT_EYE); | |
| 495 gvr::Mat4f right_eye_view_matrix = | |
| 496 gvr_api_->GetEyeFromHeadMatrix(GVR_RIGHT_EYE); | |
| 497 | |
| 498 buffer_viewport_list_->GetBufferViewport(GVR_LEFT_EYE, | |
| 499 buffer_viewport_.get()); | |
| 500 DrawWebVrEye(left_eye_view_matrix, *buffer_viewport_, present_time_nanos); | |
| 501 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE, | |
| 502 buffer_viewport_.get()); | |
| 503 DrawWebVrEye(right_eye_view_matrix, *buffer_viewport_, present_time_nanos); | |
| 504 } | |
| 505 | |
| 506 void VrShell::DrawWebVrEye(const gvr::Mat4f& view_matrix, | |
| 507 const gvr::BufferViewport& params, | |
| 508 int64_t present_time_nanos) { | |
| 509 gvr::Recti pixel_rect = | |
| 510 CalculatePixelSpaceRect(render_size_, params.GetSourceUv()); | |
| 511 glViewport(pixel_rect.left, pixel_rect.bottom, | |
| 512 pixel_rect.right - pixel_rect.left, | |
| 513 pixel_rect.top - pixel_rect.bottom); | |
| 514 glScissor(pixel_rect.left, pixel_rect.bottom, | |
| 515 pixel_rect.right - pixel_rect.left, | |
| 516 pixel_rect.top - pixel_rect.bottom); | |
| 517 | |
| 518 gvr::Mat4f projection_matrix = | |
| 519 PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar); | |
| 520 | |
| 521 if (!IsUiTextureReady()) { | |
| 522 // If the UI texture hasn't been initialized yet, we can't draw the overlay. | |
| 523 return; | |
| 451 } | 524 } |
| 525 | |
| 526 // Show IDS_WEBSITE_SETTINGS_INSECURE_WEBVR_CONTENT_PERMANENT text. | |
| 527 gvr::Mat4f icon_pos; | |
| 528 SetIdentityM(icon_pos); | |
| 529 const float small_icon_width = | |
| 530 kWebVrWarningPermanentRect.width / 1000.f * kWebVrWarningDistance; | |
| 531 const float small_icon_height = | |
| 532 kWebVrWarningPermanentRect.height / 1000.f * kWebVrWarningDistance; | |
| 533 const float small_icon_angle = | |
| 534 kWebVrWarningPermanentAngle * M_PI / 180.f; // Degrees to radians. | |
| 535 ScaleM(icon_pos, icon_pos, small_icon_width, small_icon_height, 1.0f); | |
| 536 TranslateM(icon_pos, icon_pos, 0.0f, 0.0f, -kWebVrWarningDistance); | |
| 537 icon_pos = MatrixMul( | |
| 538 QuatToMatrix(QuatFromAxisAngle(1.f, 0.f, 0.f, small_icon_angle)), | |
| 539 icon_pos); | |
| 540 gvr::Mat4f combined = MatrixMul(projection_matrix, | |
| 541 MatrixMul(view_matrix, icon_pos)); | |
| 542 vr_shell_renderer_->GetTexturedQuadRenderer()->Draw( | |
| 543 ui_texture_id_, combined, MakeUiGlCopyRect(kWebVrWarningPermanentRect)); | |
| 544 | |
| 545 // Check if we also need to show the transient warning. | |
| 546 if (present_time_nanos > webvr_warning_end_nanos_) { | |
| 547 return; | |
| 548 } | |
| 549 | |
| 550 // Show IDS_WEBSITE_SETTINGS_INSECURE_WEBVR_CONTENT_TRANSIENT text. | |
| 551 SetIdentityM(icon_pos); | |
| 552 const float large_icon_width = | |
| 553 kWebVrWarningTransientRect.width / 1000.f * kWebVrWarningDistance; | |
| 554 const float large_icon_height = | |
| 555 kWebVrWarningTransientRect.height / 1000.f * kWebVrWarningDistance; | |
| 556 ScaleM(icon_pos, icon_pos, large_icon_width, large_icon_height, 1.0f); | |
| 557 TranslateM(icon_pos, icon_pos, 0.0f, 0.0f, -kWebVrWarningDistance); | |
| 558 combined = MatrixMul(projection_matrix, | |
| 559 MatrixMul(view_matrix, icon_pos)); | |
| 560 vr_shell_renderer_->GetTexturedQuadRenderer()->Draw( | |
| 561 ui_texture_id_, combined, MakeUiGlCopyRect(kWebVrWarningTransientRect)); | |
| 562 | |
| 452 } | 563 } |
| 453 | 564 |
| 454 void VrShell::OnPause(JNIEnv* env, const JavaParamRef<jobject>& obj) { | 565 void VrShell::OnPause(JNIEnv* env, const JavaParamRef<jobject>& obj) { |
| 455 if (gvr_api_ == nullptr) | 566 if (gvr_api_ == nullptr) |
| 456 return; | 567 return; |
| 457 gvr_api_->PauseTracking(); | 568 gvr_api_->PauseTracking(); |
| 458 } | 569 } |
| 459 | 570 |
| 460 void VrShell::OnResume(JNIEnv* env, const JavaParamRef<jobject>& obj) { | 571 void VrShell::OnResume(JNIEnv* env, const JavaParamRef<jobject>& obj) { |
| 461 if (gvr_api_ == nullptr) | 572 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 | 591 // TODO(bshe): ui_text_width_ and ui_tex_height_ should be only used on render |
| 481 // thread. | 592 // thread. |
| 482 ui_tex_width_ = width; | 593 ui_tex_width_ = width; |
| 483 ui_tex_height_ = height; | 594 ui_tex_height_ = height; |
| 484 } | 595 } |
| 485 | 596 |
| 486 void VrShell::SetWebVrMode(JNIEnv* env, | 597 void VrShell::SetWebVrMode(JNIEnv* env, |
| 487 const base::android::JavaParamRef<jobject>& obj, | 598 const base::android::JavaParamRef<jobject>& obj, |
| 488 bool enabled) { | 599 bool enabled) { |
| 489 webvr_mode_ = enabled; | 600 webvr_mode_ = enabled; |
| 601 if (enabled) { | |
| 602 const int64_t warning_seconds = 30; | |
| 603 int64_t now = gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos; | |
| 604 webvr_warning_end_nanos_ = now + warning_seconds * 1000 * 1000 * 1000; | |
| 605 } else { | |
| 606 webvr_warning_end_nanos_ = 0; | |
| 607 } | |
| 490 } | 608 } |
| 491 | 609 |
| 492 void VrShell::SetWebVRSecureOrigin(bool secure_origin) { | 610 void VrShell::SetWebVRSecureOrigin(bool secure_origin) { |
| 493 webvr_secure_origin_ = secure_origin; | 611 webvr_secure_origin_ = secure_origin; |
| 494 } | 612 } |
| 495 | 613 |
| 496 void VrShell::SubmitWebVRFrame() { | 614 void VrShell::SubmitWebVRFrame() { |
| 497 } | 615 } |
| 498 | 616 |
| 499 void VrShell::UpdateWebVRTextureBounds( | 617 void VrShell::UpdateWebVRTextureBounds( |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 562 content::WebContents::FromJavaWebContents(content_web_contents)); | 680 content::WebContents::FromJavaWebContents(content_web_contents)); |
| 563 content::ContentViewCore* ui_core = content::ContentViewCore::FromWebContents( | 681 content::ContentViewCore* ui_core = content::ContentViewCore::FromWebContents( |
| 564 content::WebContents::FromJavaWebContents(ui_web_contents)); | 682 content::WebContents::FromJavaWebContents(ui_web_contents)); |
| 565 return reinterpret_cast<intptr_t>(new VrShell( | 683 return reinterpret_cast<intptr_t>(new VrShell( |
| 566 env, obj, c_core, | 684 env, obj, c_core, |
| 567 reinterpret_cast<ui::WindowAndroid*>(content_window_android), ui_core, | 685 reinterpret_cast<ui::WindowAndroid*>(content_window_android), ui_core, |
| 568 reinterpret_cast<ui::WindowAndroid*>(ui_window_android))); | 686 reinterpret_cast<ui::WindowAndroid*>(ui_window_android))); |
| 569 } | 687 } |
| 570 | 688 |
| 571 } // namespace vr_shell | 689 } // namespace vr_shell |
| OLD | NEW |