| 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 6473a6bade186fa9255299078a0af5d8cd7460bd..62c7a1dcbbd5f7719de1f23f088dfb4124892a00 100644
|
| --- a/chrome/browser/android/vr_shell/vr_shell.cc
|
| +++ b/chrome/browser/android/vr_shell/vr_shell.cc
|
| @@ -73,23 +73,6 @@ static constexpr float kReticleDistanceMultiplier = 1.5f;
|
| // 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, 250};
|
| -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
|
| -// How long the transient warning needs to be displayed.
|
| -static constexpr int64_t kWebVrWarningSeconds = 30;
|
| -
|
| static constexpr int kFramePrimaryBuffer = 0;
|
| static constexpr int kFrameHeadlockedBuffer = 1;
|
|
|
| @@ -444,6 +427,14 @@ void VrShell::DrawFrame(JNIEnv* env, const JavaParamRef<jobject>& obj) {
|
| // Bind the primary framebuffer.
|
| frame.BindBuffer(kFramePrimaryBuffer);
|
|
|
| + HandleQueuedTasks();
|
| +
|
| + // Update the render position of all UI elements (including desktop).
|
| + float screen_tilt = desktop_screen_tilt_ * M_PI / 180.0f;
|
| + scene_->UpdateTransforms(screen_tilt, UiScene::TimeInMicroseconds());
|
| +
|
| + UpdateController(GetForwardVector(head_pose));
|
| +
|
| if (webvr_mode_) {
|
| DrawWebVr();
|
|
|
| @@ -458,104 +449,98 @@ void VrShell::DrawFrame(JNIEnv* env, const JavaParamRef<jobject>& obj) {
|
| uint32_t webvr_pose_frame = GetPixelEncodedPoseIndex();
|
| head_pose = webvr_head_pose_[webvr_pose_frame % kPoseRingBufferSize];
|
| }
|
| -
|
| - // Wait for the DOM contents to be loaded before rendering to avoid drawing
|
| - // white rectangles with no content.
|
| - if (!webvr_secure_origin_ && IsUiTextureReady()) {
|
| - size_t last_viewport = buffer_viewport_list_->GetSize();
|
| - buffer_viewport_list_->SetBufferViewport(last_viewport++,
|
| - *headlocked_left_viewport_);
|
| - buffer_viewport_list_->SetBufferViewport(last_viewport++,
|
| - *headlocked_right_viewport_);
|
| -
|
| - // Bind the headlocked framebuffer.
|
| - frame.BindBuffer(kFrameHeadlockedBuffer);
|
| - DrawWebVrOverlay(target_time.monotonic_system_time_nanos);
|
| - }
|
| - } else {
|
| - DrawVrShell(head_pose);
|
| }
|
|
|
| + DrawVrShell(head_pose, frame);
|
| +
|
| frame.Unbind();
|
| frame.Submit(*buffer_viewport_list_, head_pose);
|
| }
|
|
|
| -void VrShell::DrawVrShell(const gvr::Mat4f& head_pose) {
|
| - float screen_tilt = desktop_screen_tilt_ * M_PI / 180.0f;
|
| -
|
| - HandleQueuedTasks();
|
| -
|
| - // Update the render position of all UI elements (including desktop).
|
| - scene_->UpdateTransforms(screen_tilt, UiScene::TimeInMicroseconds());
|
| +void VrShell::DrawVrShell(const gvr::Mat4f& head_pose,
|
| + gvr::Frame &frame) {
|
| + std::vector<const ContentRectangle*> head_locked_elements;
|
| + std::vector<const ContentRectangle*> world_elements;
|
| + for (const auto& rect : scene_->GetUiElements()) {
|
| + if (!rect->visible) {
|
| + continue;
|
| + }
|
| + if (webvr_mode_ && rect->id == kBrowserUiElementId) {
|
| + continue;
|
| + }
|
| + if (rect->lock_to_fov) {
|
| + head_locked_elements.push_back(rect.get());
|
| + } else {
|
| + world_elements.push_back(rect.get());
|
| + }
|
| + }
|
|
|
| - UpdateController(GetForwardVector(head_pose));
|
| + if (!webvr_mode_) {
|
| + glEnable(GL_CULL_FACE);
|
| + glEnable(GL_DEPTH_TEST);
|
| + glEnable(GL_SCISSOR_TEST);
|
| + glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
| + }
|
|
|
| - // Use culling to remove back faces.
|
| - glEnable(GL_CULL_FACE);
|
| + if (!world_elements.empty()) {
|
| + DrawUiView(&head_pose, world_elements);
|
| + }
|
|
|
| - // Enable depth testing.
|
| - glEnable(GL_DEPTH_TEST);
|
| - glEnable(GL_SCISSOR_TEST);
|
| + if (!head_locked_elements.empty()) {
|
| + // Switch to head-locked viewports.
|
| + size_t last_viewport = buffer_viewport_list_->GetSize();
|
| + buffer_viewport_list_->SetBufferViewport(last_viewport++,
|
| + *headlocked_left_viewport_);
|
| + buffer_viewport_list_->SetBufferViewport(last_viewport++,
|
| + *headlocked_right_viewport_);
|
|
|
| - glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
| + // Bind the headlocked framebuffer.
|
| + frame.BindBuffer(kFrameHeadlockedBuffer);
|
| + glClear(GL_COLOR_BUFFER_BIT);
|
|
|
| - buffer_viewport_list_->GetBufferViewport(GVR_LEFT_EYE,
|
| - buffer_viewport_.get());
|
| - DrawEye(GVR_LEFT_EYE, head_pose, *buffer_viewport_);
|
| - buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE,
|
| - buffer_viewport_.get());
|
| - DrawEye(GVR_RIGHT_EYE, head_pose, *buffer_viewport_);
|
| + DrawUiView(nullptr, head_locked_elements);
|
| + }
|
| }
|
|
|
| -void VrShell::DrawEye(gvr::Eye eye,
|
| - const gvr::Mat4f& head_pose,
|
| - const gvr::BufferViewport& params) {
|
| - gvr::Mat4f eye_matrix = gvr_api_->GetEyeFromHeadMatrix(eye);
|
| - gvr::Mat4f view_matrix = MatrixMul(eye_matrix, head_pose);
|
| -
|
| - 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);
|
| -
|
| - const gvr::Mat4f fov_render_matrix = MatrixMul(
|
| - PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar),
|
| - eye_matrix);
|
| - const gvr::Mat4f world_render_matrix = MatrixMul(
|
| - PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar),
|
| - view_matrix);
|
| +void VrShell::DrawUiView(const gvr::Mat4f* head_pose,
|
| + const std::vector<const ContentRectangle*>& elements) {
|
| + for (auto eye : {GVR_LEFT_EYE, GVR_RIGHT_EYE}) {
|
| + buffer_viewport_list_->GetBufferViewport(eye, buffer_viewport_.get());
|
|
|
| - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
| -
|
| - // TODO(mthiesse): Draw order for transparency.
|
| - DrawUI(world_render_matrix, fov_render_matrix);
|
| - DrawCursor(world_render_matrix);
|
| -}
|
| + gvr::Mat4f view_matrix = gvr_api_->GetEyeFromHeadMatrix(eye);
|
| + if (head_pose != nullptr) {
|
| + view_matrix = MatrixMul(view_matrix, *head_pose);
|
| + }
|
|
|
| -bool VrShell::IsUiTextureReady() {
|
| - return ui_tex_width_ > 0 && ui_tex_height_ > 0 && dom_contents_loaded_;
|
| -}
|
| + gvr::Recti pixel_rect =
|
| + CalculatePixelSpaceRect(render_size_, buffer_viewport_->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);
|
| +
|
| + if (!webvr_mode_) {
|
| + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
| + }
|
|
|
| -Rectf VrShell::MakeUiGlCopyRect(Recti pixel_rect) {
|
| - CHECK(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_});
|
| -}
|
| + const gvr::Mat4f render_matrix = MatrixMul(
|
| + PerspectiveMatrixFromView(
|
| + buffer_viewport_->GetSourceFov(), kZNear, kZFar),
|
| + view_matrix);
|
|
|
| -void VrShell::DrawUI(const gvr::Mat4f& world_matrix,
|
| - const gvr::Mat4f& fov_matrix) {
|
| - for (const auto& rect : scene_->GetUiElements()) {
|
| - if (!rect->visible) {
|
| - continue;
|
| + DrawElements(render_matrix, elements);
|
| + if (head_pose != nullptr) {
|
| + DrawCursor(render_matrix);
|
| }
|
| + }
|
| +}
|
|
|
| +void VrShell::DrawElements(
|
| + const gvr::Mat4f& render_matrix,
|
| + const std::vector<const ContentRectangle*>& elements) {
|
| + for (const auto& rect : elements) {
|
| Rectf copy_rect;
|
| jint texture_handle;
|
| if (rect->id == kBrowserUiElementId) {
|
| @@ -570,10 +555,7 @@ void VrShell::DrawUI(const gvr::Mat4f& world_matrix,
|
| ui_tex_height_;
|
| texture_handle = ui_texture_id_;
|
| }
|
| -
|
| - const gvr::Mat4f& view_matrix =
|
| - rect->lock_to_fov ? fov_matrix : world_matrix;
|
| - gvr::Mat4f transform = MatrixMul(view_matrix, rect->transform.to_world);
|
| + gvr::Mat4f transform = MatrixMul(render_matrix, rect->transform.to_world);
|
| vr_shell_renderer_->GetTexturedQuadRenderer()->Draw(
|
| texture_handle, transform, copy_rect);
|
| }
|
| @@ -669,88 +651,6 @@ void VrShell::DrawWebVr() {
|
| vr_shell_renderer_->GetWebVrRenderer()->Draw(content_texture_id_);
|
| }
|
|
|
| -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.
|
| -
|
| - gvr::Mat4f left_eye_view_matrix =
|
| - gvr_api_->GetEyeFromHeadMatrix(GVR_LEFT_EYE);
|
| - gvr::Mat4f right_eye_view_matrix =
|
| - gvr_api_->GetEyeFromHeadMatrix(GVR_RIGHT_EYE);
|
| -
|
| - glClear(GL_COLOR_BUFFER_BIT);
|
| -
|
| - 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);
|
| - // The UI is designed in pixels with the assumption that 1px = 1mm at 1m
|
| - // distance. Scale mm-to-m and adjust to keep the same angular size if the
|
| - // distance changes.
|
| - 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::OnTriggerEvent(JNIEnv* env, const JavaParamRef<jobject>& obj) {
|
| // Set a flag to handle this on the render thread at the next frame.
|
| touch_pending_ = true;
|
| @@ -800,18 +700,14 @@ void VrShell::SetWebVrMode(JNIEnv* env,
|
| bool enabled) {
|
| webvr_mode_ = enabled;
|
| if (enabled) {
|
| - int64_t now = gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos;
|
| - constexpr int64_t seconds_to_nanos = 1000 * 1000 * 1000;
|
| - webvr_warning_end_nanos_ = now + kWebVrWarningSeconds * seconds_to_nanos;
|
| html_interface_->SetMode(UiInterface::Mode::WEB_VR);
|
| } else {
|
| - webvr_warning_end_nanos_ = 0;
|
| html_interface_->SetMode(UiInterface::Mode::STANDARD);
|
| }
|
| }
|
|
|
| void VrShell::SetWebVRSecureOrigin(bool secure_origin) {
|
| - webvr_secure_origin_ = secure_origin;
|
| + html_interface_->SetSecureOrigin(secure_origin);
|
| }
|
|
|
| void VrShell::SubmitWebVRFrame() {
|
|
|