Chromium Code Reviews| Index: chrome/browser/android/vr_shell/vr_shell.cc |
| diff --git a/chrome/browser/android/vr_shell/vr_shell.cc b/chrome/browser/android/vr_shell/vr_shell.cc |
| index 8dfdf7f729417c73e11e32992f4f8bd532c4751c..a03f0eb8afca941dec3f00b5bd975fee05e807f3 100644 |
| --- a/chrome/browser/android/vr_shell/vr_shell.cc |
| +++ b/chrome/browser/android/vr_shell/vr_shell.cc |
| @@ -67,6 +67,21 @@ static constexpr float kReticleZOffset = 0.99f; |
| // UI element 0 is the browser content rectangle. |
| static constexpr int kBrowserUiElementId = 0; |
| +// Positions and sizes of statically placed UI elements in the UI texture. |
| +// TODO(klausw): replace the hardcoded positions with JS position/offset |
| +// retrieval once the infrastructure for that is hooked up. |
| +// |
| +// UI is designed with 1 pixel = 1mm at 1m distance. It's rescaled to |
| +// maintain the same angular resolution if placed closer or further. |
| +// The warning overlays should be fairly close since they cut holes |
| +// into geometry (they ignore the Z buffer), leading to odd effects |
| +// if they are far away. |
| +static constexpr vr_shell::Recti kWebVrWarningTransientRect = { |
| + 0, 128, 512, 256}; |
| +static constexpr vr_shell::Recti kWebVrWarningPermanentRect = {0, 0, 512, 128}; |
| +static constexpr float kWebVrWarningDistance = 0.7f; // meters |
| +static constexpr float kWebVrWarningPermanentAngle = 16.3f; // degrees up |
| + |
| vr_shell::VrShell* g_instance; |
| static const char kVrShellUIURL[] = "chrome://vr-shell-ui"; |
| @@ -274,6 +289,9 @@ void VrShell::DrawFrame(JNIEnv* env, const JavaParamRef<jobject>& obj) { |
| if (webvr_mode_) { |
| DrawWebVr(); |
| + if (!webvr_secure_origin_) { |
| + DrawWebVrOverlay(target_time.monotonic_system_time_nanos); |
| + } |
| } else { |
| DrawVrShell(); |
| } |
| @@ -352,6 +370,25 @@ void VrShell::DrawEye(const gvr::Mat4f& view_matrix, |
| DrawCursor(); |
| } |
| +bool VrShell::IsUiTextureReady() { |
| + return ui_tex_width_ > 0 && ui_tex_height_ > 0; |
| +} |
| + |
| +/** |
| + * Converts a pixel rectangle to (0..1) float texture coordinates. |
| + * |
| + * Callers need to ensure that the texture width/height is initialized |
| + * by checking IsUiTextureReady() first. |
| + */ |
|
bshe
2016/09/29 13:50:56
nit: move comment to .h file? Also, this seems lik
|
| +Rectf VrShell::MakeUiGlCopyRect(Recti pixel_rect) { |
| + DCHECK(IsUiTextureReady()); |
| + return Rectf({ |
| + static_cast<float>(pixel_rect.x) / ui_tex_width_, |
| + static_cast<float>(pixel_rect.y) / ui_tex_height_, |
| + static_cast<float>(pixel_rect.width) / ui_tex_width_, |
| + static_cast<float>(pixel_rect.height) / ui_tex_height_}); |
| +} |
| + |
| void VrShell::DrawUI() { |
| for (const auto& rect : scene_.GetUiElements()) { |
| if (!rect->visible) { |
| @@ -445,10 +482,84 @@ void VrShell::DrawWebVr() { |
| glViewport(0, 0, render_size_.width, render_size_.height); |
| vr_shell_renderer_->GetWebVrRenderer()->Draw(content_texture_id_); |
| +} |
| - if (!webvr_secure_origin_) { |
| - // TODO(klausw): Draw the insecure origin warning here. |
| +void VrShell::DrawWebVrOverlay(int64_t present_time_nanos) { |
| + // Draw WebVR security warning overlays for each eye. This uses |
| + // the eye-from-head matrices but not the pose, goal is to place |
| + // the icons in an eye-relative position so that they follow along |
| + // with head rotations. |
|
bshe
2016/09/29 13:50:56
nit: this looks like comment for function. If so,
|
| + |
| + gvr::Mat4f left_eye_view_matrix = |
| + gvr_api_->GetEyeFromHeadMatrix(GVR_LEFT_EYE); |
| + gvr::Mat4f right_eye_view_matrix = |
| + gvr_api_->GetEyeFromHeadMatrix(GVR_RIGHT_EYE); |
| + |
| + buffer_viewport_list_->GetBufferViewport(GVR_LEFT_EYE, |
| + buffer_viewport_.get()); |
| + DrawWebVrEye(left_eye_view_matrix, *buffer_viewport_, present_time_nanos); |
| + buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE, |
| + buffer_viewport_.get()); |
| + DrawWebVrEye(right_eye_view_matrix, *buffer_viewport_, present_time_nanos); |
| +} |
| + |
| +void VrShell::DrawWebVrEye(const gvr::Mat4f& view_matrix, |
| + const gvr::BufferViewport& params, |
| + int64_t present_time_nanos) { |
| + gvr::Recti pixel_rect = |
| + CalculatePixelSpaceRect(render_size_, params.GetSourceUv()); |
| + glViewport(pixel_rect.left, pixel_rect.bottom, |
| + pixel_rect.right - pixel_rect.left, |
| + pixel_rect.top - pixel_rect.bottom); |
| + glScissor(pixel_rect.left, pixel_rect.bottom, |
| + pixel_rect.right - pixel_rect.left, |
| + pixel_rect.top - pixel_rect.bottom); |
| + |
| + gvr::Mat4f projection_matrix = |
| + PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar); |
| + |
| + if (!IsUiTextureReady()) { |
| + // If the UI texture hasn't been initialized yet, we can't draw the overlay. |
| + return; |
| } |
| + |
| + // Show IDS_WEBSITE_SETTINGS_INSECURE_WEBVR_CONTENT_PERMANENT text. |
| + gvr::Mat4f icon_pos; |
| + SetIdentityM(icon_pos); |
| + const float small_icon_width = |
| + kWebVrWarningPermanentRect.width / 1000.f * kWebVrWarningDistance; |
| + const float small_icon_height = |
| + kWebVrWarningPermanentRect.height / 1000.f * kWebVrWarningDistance; |
| + const float small_icon_angle = |
| + kWebVrWarningPermanentAngle * M_PI / 180.f; // Degrees to radians. |
| + ScaleM(icon_pos, icon_pos, small_icon_width, small_icon_height, 1.0f); |
| + TranslateM(icon_pos, icon_pos, 0.0f, 0.0f, -kWebVrWarningDistance); |
| + icon_pos = MatrixMul( |
| + QuatToMatrix(QuatFromAxisAngle(1.f, 0.f, 0.f, small_icon_angle)), |
| + icon_pos); |
| + gvr::Mat4f combined = MatrixMul(projection_matrix, |
| + MatrixMul(view_matrix, icon_pos)); |
| + vr_shell_renderer_->GetTexturedQuadRenderer()->Draw( |
| + ui_texture_id_, combined, MakeUiGlCopyRect(kWebVrWarningPermanentRect)); |
| + |
| + // Check if we also need to show the transient warning. |
| + if (present_time_nanos > webvr_warning_end_nanos_) { |
| + return; |
| + } |
| + |
| + // Show IDS_WEBSITE_SETTINGS_INSECURE_WEBVR_CONTENT_TRANSIENT text. |
| + SetIdentityM(icon_pos); |
| + const float large_icon_width = |
| + kWebVrWarningTransientRect.width / 1000.f * kWebVrWarningDistance; |
| + const float large_icon_height = |
| + kWebVrWarningTransientRect.height / 1000.f * kWebVrWarningDistance; |
| + ScaleM(icon_pos, icon_pos, large_icon_width, large_icon_height, 1.0f); |
| + TranslateM(icon_pos, icon_pos, 0.0f, 0.0f, -kWebVrWarningDistance); |
| + combined = MatrixMul(projection_matrix, |
| + MatrixMul(view_matrix, icon_pos)); |
| + vr_shell_renderer_->GetTexturedQuadRenderer()->Draw( |
| + ui_texture_id_, combined, MakeUiGlCopyRect(kWebVrWarningTransientRect)); |
| + |
| } |
| void VrShell::OnPause(JNIEnv* env, const JavaParamRef<jobject>& obj) { |
| @@ -487,6 +598,13 @@ void VrShell::SetWebVrMode(JNIEnv* env, |
| const base::android::JavaParamRef<jobject>& obj, |
| bool enabled) { |
| webvr_mode_ = enabled; |
| + if (enabled) { |
| + const int64_t warning_seconds = 30; |
| + int64_t now = gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos; |
| + webvr_warning_end_nanos_ = now + warning_seconds * 1000 * 1000 * 1000; |
| + } else { |
| + webvr_warning_end_nanos_ = 0; |
| + } |
| } |
| void VrShell::SetWebVRSecureOrigin(bool secure_origin) { |