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_gl.h" | 5 #include "chrome/browser/android/vr_shell/vr_shell_gl.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/android/jni_android.h" | 10 #include "base/android/jni_android.h" |
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 webvr_right_viewport_.get()); | 468 webvr_right_viewport_.get()); |
469 webvr_right_viewport_->SetSourceBufferIndex(kFramePrimaryBuffer); | 469 webvr_right_viewport_->SetSourceBufferIndex(kFramePrimaryBuffer); |
470 | 470 |
471 main_thread_task_runner_->PostTask( | 471 main_thread_task_runner_->PostTask( |
472 FROM_HERE, base::Bind(&VrShell::GvrDelegateReady, weak_vr_shell_)); | 472 FROM_HERE, base::Bind(&VrShell::GvrDelegateReady, weak_vr_shell_)); |
473 } | 473 } |
474 | 474 |
475 void VrShellGl::UpdateController(const gvr::Vec3f& forward_vector) { | 475 void VrShellGl::UpdateController(const gvr::Vec3f& forward_vector) { |
476 controller_->UpdateState(); | 476 controller_->UpdateState(); |
477 | 477 |
478 if (web_vr_mode_) { | 478 if (ShouldDrawWebVr()) { |
479 // Process screen touch events for Cardboard button compatibility. | 479 // Process screen touch events for Cardboard button compatibility. |
480 // Also send tap events for controller "touchpad click" events. | 480 // Also send tap events for controller "touchpad click" events. |
481 if (touch_pending_ || | 481 if (touch_pending_ || |
482 controller_->ButtonUpHappened( | 482 controller_->ButtonUpHappened( |
483 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK)) { | 483 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK)) { |
484 touch_pending_ = false; | 484 touch_pending_ = false; |
485 std::unique_ptr<WebGestureEvent> gesture(new WebGestureEvent( | 485 std::unique_ptr<WebGestureEvent> gesture(new WebGestureEvent( |
486 WebInputEvent::GestureTapDown, WebInputEvent::NoModifiers, | 486 WebInputEvent::GestureTapDown, WebInputEvent::NoModifiers, |
487 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF())); | 487 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF())); |
488 gesture->sourceDevice = blink::WebGestureDeviceTouchpad; | 488 gesture->sourceDevice = blink::WebGestureDeviceTouchpad; |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
710 void VrShellGl::DrawFrame(int16_t frame_index) { | 710 void VrShellGl::DrawFrame(int16_t frame_index) { |
711 TRACE_EVENT1("gpu", "VrShellGl::DrawFrame", "frame", frame_index); | 711 TRACE_EVENT1("gpu", "VrShellGl::DrawFrame", "frame", frame_index); |
712 | 712 |
713 // Reset the viewport list to just the pair of viewports for the | 713 // Reset the viewport list to just the pair of viewports for the |
714 // primary buffer each frame. Head-locked viewports get added by | 714 // primary buffer each frame. Head-locked viewports get added by |
715 // DrawVrShell if needed. | 715 // DrawVrShell if needed. |
716 buffer_viewport_list_->SetToRecommendedBufferViewports(); | 716 buffer_viewport_list_->SetToRecommendedBufferViewports(); |
717 | 717 |
718 // If needed, resize the primary buffer for use with WebVR. Resizing | 718 // If needed, resize the primary buffer for use with WebVR. Resizing |
719 // needs to happen before acquiring a frame. | 719 // needs to happen before acquiring a frame. |
720 if (web_vr_mode_) { | 720 if (ShouldDrawWebVr()) { |
721 // Process all pending_bounds_ changes targeted for before this | 721 // Process all pending_bounds_ changes targeted for before this |
722 // frame, being careful of wrapping frame indices. | 722 // frame, being careful of wrapping frame indices. |
723 static constexpr unsigned max = | 723 static constexpr unsigned max = |
724 std::numeric_limits<decltype(frame_index_)>::max(); | 724 std::numeric_limits<decltype(frame_index_)>::max(); |
725 static_assert(max > kPoseRingBufferSize * 2, | 725 static_assert(max > kPoseRingBufferSize * 2, |
726 "To detect wrapping, kPoseRingBufferSize must be smaller " | 726 "To detect wrapping, kPoseRingBufferSize must be smaller " |
727 "than half of frame_index_ range."); | 727 "than half of frame_index_ range."); |
728 while (!pending_bounds_.empty()) { | 728 while (!pending_bounds_.empty()) { |
729 uint16_t index = pending_bounds_.front().first; | 729 uint16_t index = pending_bounds_.front().first; |
730 // If index is less than the frame_index it's possible we've | 730 // If index is less than the frame_index it's possible we've |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
772 } | 772 } |
773 | 773 |
774 TRACE_EVENT_BEGIN0("gpu", "VrShellGl::AcquireFrame"); | 774 TRACE_EVENT_BEGIN0("gpu", "VrShellGl::AcquireFrame"); |
775 gvr::Frame frame = swap_chain_->AcquireFrame(); | 775 gvr::Frame frame = swap_chain_->AcquireFrame(); |
776 TRACE_EVENT_END0("gpu", "VrShellGl::AcquireFrame"); | 776 TRACE_EVENT_END0("gpu", "VrShellGl::AcquireFrame"); |
777 if (!frame.is_valid()) { | 777 if (!frame.is_valid()) { |
778 return; | 778 return; |
779 } | 779 } |
780 frame.BindBuffer(kFramePrimaryBuffer); | 780 frame.BindBuffer(kFramePrimaryBuffer); |
781 | 781 |
782 if (web_vr_mode_) { | 782 if (ShouldDrawWebVr()) { |
783 DrawWebVr(); | 783 DrawWebVr(); |
784 } | 784 } |
785 | 785 |
786 gvr::Mat4f head_pose; | 786 gvr::Mat4f head_pose; |
787 | 787 |
788 // When using async reprojection, we need to know which pose was | 788 // When using async reprojection, we need to know which pose was |
789 // used in the WebVR app for drawing this frame and supply it when | 789 // used in the WebVR app for drawing this frame and supply it when |
790 // submitting. Technically we don't need a pose if not reprojecting, | 790 // submitting. Technically we don't need a pose if not reprojecting, |
791 // but keeping it uninitialized seems likely to cause problems down | 791 // but keeping it uninitialized seems likely to cause problems down |
792 // the road. Copying it is cheaper than fetching a new one. | 792 // the road. Copying it is cheaper than fetching a new one. |
793 if (web_vr_mode_) { | 793 if (ShouldDrawWebVr()) { |
794 static_assert(!((kPoseRingBufferSize - 1) & kPoseRingBufferSize), | 794 static_assert(!((kPoseRingBufferSize - 1) & kPoseRingBufferSize), |
795 "kPoseRingBufferSize must be a power of 2"); | 795 "kPoseRingBufferSize must be a power of 2"); |
796 head_pose = webvr_head_pose_[frame_index % kPoseRingBufferSize]; | 796 head_pose = webvr_head_pose_[frame_index % kPoseRingBufferSize]; |
797 } else { | 797 } else { |
798 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); | 798 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); |
799 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; | 799 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; |
800 head_pose = gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time); | 800 head_pose = gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time); |
801 } | 801 } |
802 | 802 |
803 gvr::Vec3f position = GetTranslation(head_pose); | 803 gvr::Vec3f position = GetTranslation(head_pose); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
844 for (const auto& rect : scene_->GetUiElements()) { | 844 for (const auto& rect : scene_->GetUiElements()) { |
845 if (!rect->IsVisible()) | 845 if (!rect->IsVisible()) |
846 continue; | 846 continue; |
847 if (rect->computed_lock_to_fov) { | 847 if (rect->computed_lock_to_fov) { |
848 head_locked_elements.push_back(rect.get()); | 848 head_locked_elements.push_back(rect.get()); |
849 } else { | 849 } else { |
850 world_elements.push_back(rect.get()); | 850 world_elements.push_back(rect.get()); |
851 } | 851 } |
852 } | 852 } |
853 | 853 |
854 if (web_vr_mode_) { | 854 if (ShouldDrawWebVr()) { |
855 // WebVR is incompatible with 3D world compositing since the | 855 // WebVR is incompatible with 3D world compositing since the |
856 // depth buffer was already populated with unknown scaling - the | 856 // depth buffer was already populated with unknown scaling - the |
857 // WebVR app has full control over zNear/zFar. Just leave the | 857 // WebVR app has full control over zNear/zFar. Just leave the |
858 // existing content in place in the primary buffer without | 858 // existing content in place in the primary buffer without |
859 // clearing. Currently, there aren't any world elements in WebVR | 859 // clearing. Currently, there aren't any world elements in WebVR |
860 // mode, this will need further testing if those get added | 860 // mode, this will need further testing if those get added |
861 // later. | 861 // later. |
862 } else { | 862 } else { |
863 // Non-WebVR mode, enable depth testing and clear the primary buffers. | 863 // Non-WebVR mode, enable depth testing and clear the primary buffers. |
864 glEnable(GL_CULL_FACE); | 864 glEnable(GL_CULL_FACE); |
865 glEnable(GL_DEPTH_TEST); | 865 glEnable(GL_DEPTH_TEST); |
866 glDepthMask(GL_TRUE); | 866 glDepthMask(GL_TRUE); |
867 | 867 |
868 const Colorf& backgroundColor = scene_->GetBackgroundColor(); | 868 const Colorf& backgroundColor = scene_->GetBackgroundColor(); |
869 glClearColor(backgroundColor.r, backgroundColor.g, backgroundColor.b, | 869 glClearColor(backgroundColor.r, backgroundColor.g, backgroundColor.b, |
870 backgroundColor.a); | 870 backgroundColor.a); |
871 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | 871 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
872 } | 872 } |
873 if (!world_elements.empty()) { | 873 if (!world_elements.empty()) { |
874 DrawUiView(&head_pose, world_elements, render_size_primary_, | 874 DrawUiView(head_pose, world_elements, render_size_primary_, |
875 kViewportListPrimaryOffset); | 875 kViewportListPrimaryOffset, !ShouldDrawWebVr()); |
876 } | 876 } |
877 frame.Unbind(); // Done with the primary buffer. | 877 frame.Unbind(); // Done with the primary buffer. |
878 | 878 |
879 if (!head_locked_elements.empty()) { | 879 if (!head_locked_elements.empty()) { |
880 // Add head-locked viewports. The list gets reset to just | 880 // Add head-locked viewports. The list gets reset to just |
881 // the recommended viewports (for the primary buffer) each frame. | 881 // the recommended viewports (for the primary buffer) each frame. |
882 buffer_viewport_list_->SetBufferViewport( | 882 buffer_viewport_list_->SetBufferViewport( |
883 kViewportListHeadlockedOffset + GVR_LEFT_EYE, | 883 kViewportListHeadlockedOffset + GVR_LEFT_EYE, |
884 *headlocked_left_viewport_); | 884 *headlocked_left_viewport_); |
885 buffer_viewport_list_->SetBufferViewport( | 885 buffer_viewport_list_->SetBufferViewport( |
886 kViewportListHeadlockedOffset + GVR_RIGHT_EYE, | 886 kViewportListHeadlockedOffset + GVR_RIGHT_EYE, |
887 *headlocked_right_viewport_); | 887 *headlocked_right_viewport_); |
888 | 888 |
889 // Bind the headlocked framebuffer. | 889 // Bind the headlocked framebuffer. |
890 frame.BindBuffer(kFrameHeadlockedBuffer); | 890 frame.BindBuffer(kFrameHeadlockedBuffer); |
891 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); | 891 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); |
892 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | 892 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
893 DrawUiView(nullptr, head_locked_elements, render_size_headlocked_, | 893 gvr::Mat4f identity_matrix; |
894 kViewportListHeadlockedOffset); | 894 SetIdentityM(identity_matrix); |
| 895 DrawUiView(identity_matrix, head_locked_elements, render_size_headlocked_, |
| 896 kViewportListHeadlockedOffset, false); |
895 frame.Unbind(); // Done with the headlocked buffer. | 897 frame.Unbind(); // Done with the headlocked buffer. |
896 } | 898 } |
897 } | 899 } |
898 | 900 |
899 void VrShellGl::DrawUiView(const gvr::Mat4f* head_pose, | 901 void VrShellGl::DrawUiView(const gvr::Mat4f& head_pose, |
900 const std::vector<const ContentRectangle*>& elements, | 902 const std::vector<const ContentRectangle*>& elements, |
901 const gvr::Sizei& render_size, | 903 const gvr::Sizei& render_size, |
902 int viewport_offset) { | 904 int viewport_offset, |
| 905 bool draw_cursor) { |
903 TRACE_EVENT0("gpu", "VrShellGl::DrawUiView"); | 906 TRACE_EVENT0("gpu", "VrShellGl::DrawUiView"); |
904 | 907 |
905 gvr::Mat4f view_matrix; | 908 auto elementsInDrawOrder = GetElementsInDrawOrder(head_pose, elements); |
906 if (head_pose) { | |
907 view_matrix = *head_pose; | |
908 } else { | |
909 SetIdentityM(view_matrix); | |
910 } | |
911 auto elementsInDrawOrder = GetElementsInDrawOrder(view_matrix, elements); | |
912 | 909 |
913 for (auto eye : {GVR_LEFT_EYE, GVR_RIGHT_EYE}) { | 910 for (auto eye : {GVR_LEFT_EYE, GVR_RIGHT_EYE}) { |
914 buffer_viewport_list_->GetBufferViewport(eye + viewport_offset, | 911 buffer_viewport_list_->GetBufferViewport(eye + viewport_offset, |
915 buffer_viewport_.get()); | 912 buffer_viewport_.get()); |
916 | 913 |
917 const gvr::Mat4f eye_view_matrix = | 914 const gvr::Mat4f eye_view_matrix = |
918 MatrixMul(gvr_api_->GetEyeFromHeadMatrix(eye), view_matrix); | 915 MatrixMul(gvr_api_->GetEyeFromHeadMatrix(eye), head_pose); |
919 | 916 |
920 gvr::Recti pixel_rect = | 917 gvr::Recti pixel_rect = |
921 CalculatePixelSpaceRect(render_size, buffer_viewport_->GetSourceUv()); | 918 CalculatePixelSpaceRect(render_size, buffer_viewport_->GetSourceUv()); |
922 glViewport(pixel_rect.left, pixel_rect.bottom, | 919 glViewport(pixel_rect.left, pixel_rect.bottom, |
923 pixel_rect.right - pixel_rect.left, | 920 pixel_rect.right - pixel_rect.left, |
924 pixel_rect.top - pixel_rect.bottom); | 921 pixel_rect.top - pixel_rect.bottom); |
925 | 922 |
926 const gvr::Mat4f render_matrix = | 923 const gvr::Mat4f render_matrix = |
927 MatrixMul(PerspectiveMatrixFromView(buffer_viewport_->GetSourceFov(), | 924 MatrixMul(PerspectiveMatrixFromView(buffer_viewport_->GetSourceFov(), |
928 kZNear, kZFar), | 925 kZNear, kZFar), |
929 eye_view_matrix); | 926 eye_view_matrix); |
930 | 927 |
931 DrawElements(render_matrix, eye_view_matrix, elementsInDrawOrder); | 928 DrawElements(render_matrix, elementsInDrawOrder); |
932 if (head_pose != nullptr && !web_vr_mode_) { | 929 if (draw_cursor) { |
933 DrawCursor(render_matrix); | 930 DrawCursor(render_matrix); |
934 } | 931 } |
935 } | 932 } |
936 } | 933 } |
937 | 934 |
938 void VrShellGl::DrawElements( | 935 void VrShellGl::DrawElements( |
939 const gvr::Mat4f& view_proj_matrix, | 936 const gvr::Mat4f& view_proj_matrix, |
940 const gvr::Mat4f& view_matrix, | |
941 const std::vector<const ContentRectangle*>& elements) { | 937 const std::vector<const ContentRectangle*>& elements) { |
942 for (const auto* rect : elements) { | 938 for (const auto* rect : elements) { |
943 gvr::Mat4f transform = MatrixMul(view_proj_matrix, rect->TransformMatrix()); | 939 gvr::Mat4f transform = MatrixMul(view_proj_matrix, rect->TransformMatrix()); |
944 | 940 |
945 switch (rect->fill) { | 941 switch (rect->fill) { |
946 case Fill::SPRITE: { | 942 case Fill::SPRITE: { |
947 Rectf copy_rect; | 943 Rectf copy_rect; |
948 copy_rect.x = static_cast<float>(rect->copy_rect.x) / ui_tex_css_width_; | 944 copy_rect.x = static_cast<float>(rect->copy_rect.x) / ui_tex_css_width_; |
949 copy_rect.y = | 945 copy_rect.y = |
950 static_cast<float>(rect->copy_rect.y) / ui_tex_css_height_; | 946 static_cast<float>(rect->copy_rect.y) / ui_tex_css_height_; |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1085 | 1081 |
1086 // Move the beam origin to the hand. | 1082 // Move the beam origin to the hand. |
1087 TranslateM(face_transform, face_transform, kHandPosition.x, kHandPosition.y, | 1083 TranslateM(face_transform, face_transform, kHandPosition.x, kHandPosition.y, |
1088 kHandPosition.z); | 1084 kHandPosition.z); |
1089 | 1085 |
1090 transform = MatrixMul(render_matrix, face_transform); | 1086 transform = MatrixMul(render_matrix, face_transform); |
1091 vr_shell_renderer_->GetLaserRenderer()->Draw(transform); | 1087 vr_shell_renderer_->GetLaserRenderer()->Draw(transform); |
1092 } | 1088 } |
1093 } | 1089 } |
1094 | 1090 |
| 1091 bool VrShellGl::ShouldDrawWebVr() { |
| 1092 return web_vr_mode_ && scene_->GetWebVrRenderingEnabled(); |
| 1093 } |
| 1094 |
1095 void VrShellGl::DrawWebVr() { | 1095 void VrShellGl::DrawWebVr() { |
1096 TRACE_EVENT0("gpu", "VrShellGl::DrawWebVr"); | 1096 TRACE_EVENT0("gpu", "VrShellGl::DrawWebVr"); |
1097 // Don't need face culling, depth testing, blending, etc. Turn it all off. | 1097 // Don't need face culling, depth testing, blending, etc. Turn it all off. |
1098 glDisable(GL_CULL_FACE); | 1098 glDisable(GL_CULL_FACE); |
1099 glDepthMask(GL_FALSE); | 1099 glDepthMask(GL_FALSE); |
1100 glDisable(GL_DEPTH_TEST); | 1100 glDisable(GL_DEPTH_TEST); |
1101 glDisable(GL_SCISSOR_TEST); | 1101 glDisable(GL_SCISSOR_TEST); |
1102 glDisable(GL_BLEND); | 1102 glDisable(GL_BLEND); |
1103 glDisable(GL_POLYGON_OFFSET_FILL); | 1103 glDisable(GL_POLYGON_OFFSET_FILL); |
1104 | 1104 |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1201 task_runner_->PostDelayedTask(FROM_HERE, vsync_task_.callback(), | 1201 task_runner_->PostDelayedTask(FROM_HERE, vsync_task_.callback(), |
1202 target - now); | 1202 target - now); |
1203 | 1203 |
1204 base::TimeDelta time = intervals * vsync_interval_; | 1204 base::TimeDelta time = intervals * vsync_interval_; |
1205 if (!callback_.is_null()) { | 1205 if (!callback_.is_null()) { |
1206 SendVSync(time, base::ResetAndReturn(&callback_)); | 1206 SendVSync(time, base::ResetAndReturn(&callback_)); |
1207 } else { | 1207 } else { |
1208 pending_vsync_ = true; | 1208 pending_vsync_ = true; |
1209 pending_time_ = time; | 1209 pending_time_ = time; |
1210 } | 1210 } |
1211 if (!web_vr_mode_) { | 1211 if (!ShouldDrawWebVr()) { |
1212 DrawFrame(-1); | 1212 DrawFrame(-1); |
1213 } | 1213 } |
1214 } | 1214 } |
1215 | 1215 |
1216 void VrShellGl::OnRequest(device::mojom::VRVSyncProviderRequest request) { | 1216 void VrShellGl::OnRequest(device::mojom::VRVSyncProviderRequest request) { |
1217 binding_.Close(); | 1217 binding_.Close(); |
1218 binding_.Bind(std::move(request)); | 1218 binding_.Bind(std::move(request)); |
1219 } | 1219 } |
1220 | 1220 |
1221 void VrShellGl::GetVSync(const GetVSyncCallback& callback) { | 1221 void VrShellGl::GetVSync(const GetVSyncCallback& callback) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1284 // appropriate recommended render resolution as the default size during | 1284 // appropriate recommended render resolution as the default size during |
1285 // InitializeGl. Revisit if the initialization order changes. | 1285 // InitializeGl. Revisit if the initialization order changes. |
1286 device::mojom::VRDisplayInfoPtr info = VrShell::CreateVRDisplayInfo( | 1286 device::mojom::VRDisplayInfoPtr info = VrShell::CreateVRDisplayInfo( |
1287 gvr_api_.get(), webvr_surface_size_, device_id); | 1287 gvr_api_.get(), webvr_surface_size_, device_id); |
1288 main_thread_task_runner_->PostTask( | 1288 main_thread_task_runner_->PostTask( |
1289 FROM_HERE, | 1289 FROM_HERE, |
1290 base::Bind(&RunVRDisplayInfoCallback, callback, base::Passed(&info))); | 1290 base::Bind(&RunVRDisplayInfoCallback, callback, base::Passed(&info))); |
1291 } | 1291 } |
1292 | 1292 |
1293 } // namespace vr_shell | 1293 } // namespace vr_shell |
OLD | NEW |