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 // TODO(crbug.com/680253): Do not compare the constants on every frame. | |
mthiesse
2017/03/20 17:32:16
Note that this is a static assert and is checked b
cjgrant
2017/03/20 17:57:22
Done. Sweet, I learned something cool today!
| |
723 static constexpr unsigned max = | 724 static constexpr unsigned max = |
724 std::numeric_limits<decltype(frame_index_)>::max(); | 725 std::numeric_limits<decltype(frame_index_)>::max(); |
725 static_assert(max > kPoseRingBufferSize * 2, | 726 static_assert(max > kPoseRingBufferSize * 2, |
726 "To detect wrapping, kPoseRingBufferSize must be smaller " | 727 "To detect wrapping, kPoseRingBufferSize must be smaller " |
727 "than half of frame_index_ range."); | 728 "than half of frame_index_ range."); |
728 while (!pending_bounds_.empty()) { | 729 while (!pending_bounds_.empty()) { |
729 uint16_t index = pending_bounds_.front().first; | 730 uint16_t index = pending_bounds_.front().first; |
730 // If index is less than the frame_index it's possible we've | 731 // If index is less than the frame_index it's possible we've |
731 // wrapped, so we extend the range and 'un-wrap' to account | 732 // wrapped, so we extend the range and 'un-wrap' to account |
732 // for this. | 733 // for this. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
772 } | 773 } |
773 | 774 |
774 TRACE_EVENT_BEGIN0("gpu", "VrShellGl::AcquireFrame"); | 775 TRACE_EVENT_BEGIN0("gpu", "VrShellGl::AcquireFrame"); |
775 gvr::Frame frame = swap_chain_->AcquireFrame(); | 776 gvr::Frame frame = swap_chain_->AcquireFrame(); |
776 TRACE_EVENT_END0("gpu", "VrShellGl::AcquireFrame"); | 777 TRACE_EVENT_END0("gpu", "VrShellGl::AcquireFrame"); |
777 if (!frame.is_valid()) { | 778 if (!frame.is_valid()) { |
778 return; | 779 return; |
779 } | 780 } |
780 frame.BindBuffer(kFramePrimaryBuffer); | 781 frame.BindBuffer(kFramePrimaryBuffer); |
781 | 782 |
782 if (web_vr_mode_) { | 783 if (ShouldDrawWebVr()) { |
783 DrawWebVr(); | 784 DrawWebVr(); |
784 } | 785 } |
785 | 786 |
786 gvr::Mat4f head_pose; | 787 gvr::Mat4f head_pose; |
787 | 788 |
788 // When using async reprojection, we need to know which pose was | 789 // 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 | 790 // 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, | 791 // submitting. Technically we don't need a pose if not reprojecting, |
791 // but keeping it uninitialized seems likely to cause problems down | 792 // but keeping it uninitialized seems likely to cause problems down |
792 // the road. Copying it is cheaper than fetching a new one. | 793 // the road. Copying it is cheaper than fetching a new one. |
793 if (web_vr_mode_) { | 794 if (ShouldDrawWebVr()) { |
795 // TODO(crbug.com/680253): Do not compare the constants on every frame. | |
mthiesse
2017/03/20 17:32:16
Same as above.
| |
794 static_assert(!((kPoseRingBufferSize - 1) & kPoseRingBufferSize), | 796 static_assert(!((kPoseRingBufferSize - 1) & kPoseRingBufferSize), |
795 "kPoseRingBufferSize must be a power of 2"); | 797 "kPoseRingBufferSize must be a power of 2"); |
796 head_pose = webvr_head_pose_[frame_index % kPoseRingBufferSize]; | 798 head_pose = webvr_head_pose_[frame_index % kPoseRingBufferSize]; |
797 } else { | 799 } else { |
798 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); | 800 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); |
799 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; | 801 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; |
800 head_pose = gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time); | 802 head_pose = gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time); |
801 } | 803 } |
802 | 804 |
803 gvr::Vec3f position = GetTranslation(head_pose); | 805 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()) { | 846 for (const auto& rect : scene_->GetUiElements()) { |
845 if (!rect->IsVisible()) | 847 if (!rect->IsVisible()) |
846 continue; | 848 continue; |
847 if (rect->computed_lock_to_fov) { | 849 if (rect->computed_lock_to_fov) { |
848 head_locked_elements.push_back(rect.get()); | 850 head_locked_elements.push_back(rect.get()); |
849 } else { | 851 } else { |
850 world_elements.push_back(rect.get()); | 852 world_elements.push_back(rect.get()); |
851 } | 853 } |
852 } | 854 } |
853 | 855 |
854 if (web_vr_mode_) { | 856 if (ShouldDrawWebVr()) { |
855 // WebVR is incompatible with 3D world compositing since the | 857 // WebVR is incompatible with 3D world compositing since the |
856 // depth buffer was already populated with unknown scaling - the | 858 // depth buffer was already populated with unknown scaling - the |
857 // WebVR app has full control over zNear/zFar. Just leave the | 859 // WebVR app has full control over zNear/zFar. Just leave the |
858 // existing content in place in the primary buffer without | 860 // existing content in place in the primary buffer without |
859 // clearing. Currently, there aren't any world elements in WebVR | 861 // clearing. Currently, there aren't any world elements in WebVR |
860 // mode, this will need further testing if those get added | 862 // mode, this will need further testing if those get added |
861 // later. | 863 // later. |
862 } else { | 864 } else { |
863 // Non-WebVR mode, enable depth testing and clear the primary buffers. | 865 // Non-WebVR mode, enable depth testing and clear the primary buffers. |
864 glEnable(GL_CULL_FACE); | 866 glEnable(GL_CULL_FACE); |
865 glEnable(GL_DEPTH_TEST); | 867 glEnable(GL_DEPTH_TEST); |
866 glDepthMask(GL_TRUE); | 868 glDepthMask(GL_TRUE); |
867 | 869 |
868 const Colorf& backgroundColor = scene_->GetBackgroundColor(); | 870 const Colorf& backgroundColor = scene_->GetBackgroundColor(); |
869 glClearColor(backgroundColor.r, backgroundColor.g, backgroundColor.b, | 871 glClearColor(backgroundColor.r, backgroundColor.g, backgroundColor.b, |
870 backgroundColor.a); | 872 backgroundColor.a); |
871 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | 873 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
872 } | 874 } |
873 if (!world_elements.empty()) { | 875 if (!world_elements.empty()) { |
874 DrawUiView(&head_pose, world_elements, render_size_primary_, | 876 DrawUiView(head_pose, world_elements, render_size_primary_, |
875 kViewportListPrimaryOffset); | 877 kViewportListPrimaryOffset, !ShouldDrawWebVr()); |
876 } | 878 } |
877 frame.Unbind(); // Done with the primary buffer. | 879 frame.Unbind(); // Done with the primary buffer. |
878 | 880 |
879 if (!head_locked_elements.empty()) { | 881 if (!head_locked_elements.empty()) { |
880 // Add head-locked viewports. The list gets reset to just | 882 // Add head-locked viewports. The list gets reset to just |
881 // the recommended viewports (for the primary buffer) each frame. | 883 // the recommended viewports (for the primary buffer) each frame. |
882 buffer_viewport_list_->SetBufferViewport( | 884 buffer_viewport_list_->SetBufferViewport( |
883 kViewportListHeadlockedOffset + GVR_LEFT_EYE, | 885 kViewportListHeadlockedOffset + GVR_LEFT_EYE, |
884 *headlocked_left_viewport_); | 886 *headlocked_left_viewport_); |
885 buffer_viewport_list_->SetBufferViewport( | 887 buffer_viewport_list_->SetBufferViewport( |
886 kViewportListHeadlockedOffset + GVR_RIGHT_EYE, | 888 kViewportListHeadlockedOffset + GVR_RIGHT_EYE, |
887 *headlocked_right_viewport_); | 889 *headlocked_right_viewport_); |
888 | 890 |
889 // Bind the headlocked framebuffer. | 891 // Bind the headlocked framebuffer. |
890 frame.BindBuffer(kFrameHeadlockedBuffer); | 892 frame.BindBuffer(kFrameHeadlockedBuffer); |
891 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); | 893 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); |
892 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | 894 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
893 DrawUiView(nullptr, head_locked_elements, render_size_headlocked_, | 895 gvr::Mat4f identity_matrix; |
894 kViewportListHeadlockedOffset); | 896 SetIdentityM(identity_matrix); |
897 DrawUiView(identity_matrix, head_locked_elements, render_size_headlocked_, | |
898 kViewportListHeadlockedOffset, false); | |
895 frame.Unbind(); // Done with the headlocked buffer. | 899 frame.Unbind(); // Done with the headlocked buffer. |
896 } | 900 } |
897 } | 901 } |
898 | 902 |
899 void VrShellGl::DrawUiView(const gvr::Mat4f* head_pose, | 903 void VrShellGl::DrawUiView(const gvr::Mat4f& head_pose, |
900 const std::vector<const ContentRectangle*>& elements, | 904 const std::vector<const ContentRectangle*>& elements, |
901 const gvr::Sizei& render_size, | 905 const gvr::Sizei& render_size, |
902 int viewport_offset) { | 906 int viewport_offset, |
907 bool draw_cursor) { | |
903 TRACE_EVENT0("gpu", "VrShellGl::DrawUiView"); | 908 TRACE_EVENT0("gpu", "VrShellGl::DrawUiView"); |
904 | 909 |
905 gvr::Mat4f view_matrix; | 910 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 | 911 |
913 for (auto eye : {GVR_LEFT_EYE, GVR_RIGHT_EYE}) { | 912 for (auto eye : {GVR_LEFT_EYE, GVR_RIGHT_EYE}) { |
914 buffer_viewport_list_->GetBufferViewport(eye + viewport_offset, | 913 buffer_viewport_list_->GetBufferViewport(eye + viewport_offset, |
915 buffer_viewport_.get()); | 914 buffer_viewport_.get()); |
916 | 915 |
917 const gvr::Mat4f eye_view_matrix = | 916 const gvr::Mat4f eye_view_matrix = |
918 MatrixMul(gvr_api_->GetEyeFromHeadMatrix(eye), view_matrix); | 917 MatrixMul(gvr_api_->GetEyeFromHeadMatrix(eye), head_pose); |
919 | 918 |
920 gvr::Recti pixel_rect = | 919 gvr::Recti pixel_rect = |
921 CalculatePixelSpaceRect(render_size, buffer_viewport_->GetSourceUv()); | 920 CalculatePixelSpaceRect(render_size, buffer_viewport_->GetSourceUv()); |
922 glViewport(pixel_rect.left, pixel_rect.bottom, | 921 glViewport(pixel_rect.left, pixel_rect.bottom, |
923 pixel_rect.right - pixel_rect.left, | 922 pixel_rect.right - pixel_rect.left, |
924 pixel_rect.top - pixel_rect.bottom); | 923 pixel_rect.top - pixel_rect.bottom); |
925 | 924 |
926 const gvr::Mat4f render_matrix = | 925 const gvr::Mat4f render_matrix = |
927 MatrixMul(PerspectiveMatrixFromView(buffer_viewport_->GetSourceFov(), | 926 MatrixMul(PerspectiveMatrixFromView(buffer_viewport_->GetSourceFov(), |
928 kZNear, kZFar), | 927 kZNear, kZFar), |
929 eye_view_matrix); | 928 eye_view_matrix); |
930 | 929 |
931 DrawElements(render_matrix, eye_view_matrix, elementsInDrawOrder); | 930 DrawElements(render_matrix, elementsInDrawOrder); |
932 if (head_pose != nullptr && !web_vr_mode_) { | 931 if (draw_cursor) { |
933 DrawCursor(render_matrix); | 932 DrawCursor(render_matrix); |
934 } | 933 } |
935 } | 934 } |
936 } | 935 } |
937 | 936 |
938 void VrShellGl::DrawElements( | 937 void VrShellGl::DrawElements( |
939 const gvr::Mat4f& view_proj_matrix, | 938 const gvr::Mat4f& view_proj_matrix, |
940 const gvr::Mat4f& view_matrix, | |
941 const std::vector<const ContentRectangle*>& elements) { | 939 const std::vector<const ContentRectangle*>& elements) { |
942 for (const auto* rect : elements) { | 940 for (const auto* rect : elements) { |
943 gvr::Mat4f transform = MatrixMul(view_proj_matrix, rect->TransformMatrix()); | 941 gvr::Mat4f transform = MatrixMul(view_proj_matrix, rect->TransformMatrix()); |
944 | 942 |
945 switch (rect->fill) { | 943 switch (rect->fill) { |
946 case Fill::SPRITE: { | 944 case Fill::SPRITE: { |
947 Rectf copy_rect; | 945 Rectf copy_rect; |
948 copy_rect.x = static_cast<float>(rect->copy_rect.x) / ui_tex_css_width_; | 946 copy_rect.x = static_cast<float>(rect->copy_rect.x) / ui_tex_css_width_; |
949 copy_rect.y = | 947 copy_rect.y = |
950 static_cast<float>(rect->copy_rect.y) / ui_tex_css_height_; | 948 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 | 1083 |
1086 // Move the beam origin to the hand. | 1084 // Move the beam origin to the hand. |
1087 TranslateM(face_transform, face_transform, kHandPosition.x, kHandPosition.y, | 1085 TranslateM(face_transform, face_transform, kHandPosition.x, kHandPosition.y, |
1088 kHandPosition.z); | 1086 kHandPosition.z); |
1089 | 1087 |
1090 transform = MatrixMul(render_matrix, face_transform); | 1088 transform = MatrixMul(render_matrix, face_transform); |
1091 vr_shell_renderer_->GetLaserRenderer()->Draw(transform); | 1089 vr_shell_renderer_->GetLaserRenderer()->Draw(transform); |
1092 } | 1090 } |
1093 } | 1091 } |
1094 | 1092 |
1093 bool VrShellGl::ShouldDrawWebVr() { | |
1094 return web_vr_mode_ && scene_->GetWebVrRenderingEnabled(); | |
1095 } | |
1096 | |
1095 void VrShellGl::DrawWebVr() { | 1097 void VrShellGl::DrawWebVr() { |
1096 TRACE_EVENT0("gpu", "VrShellGl::DrawWebVr"); | 1098 TRACE_EVENT0("gpu", "VrShellGl::DrawWebVr"); |
1097 // Don't need face culling, depth testing, blending, etc. Turn it all off. | 1099 // Don't need face culling, depth testing, blending, etc. Turn it all off. |
1098 glDisable(GL_CULL_FACE); | 1100 glDisable(GL_CULL_FACE); |
1099 glDepthMask(GL_FALSE); | 1101 glDepthMask(GL_FALSE); |
1100 glDisable(GL_DEPTH_TEST); | 1102 glDisable(GL_DEPTH_TEST); |
1101 glDisable(GL_SCISSOR_TEST); | 1103 glDisable(GL_SCISSOR_TEST); |
1102 glDisable(GL_BLEND); | 1104 glDisable(GL_BLEND); |
1103 glDisable(GL_POLYGON_OFFSET_FILL); | 1105 glDisable(GL_POLYGON_OFFSET_FILL); |
1104 | 1106 |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1201 task_runner_->PostDelayedTask(FROM_HERE, vsync_task_.callback(), | 1203 task_runner_->PostDelayedTask(FROM_HERE, vsync_task_.callback(), |
1202 target - now); | 1204 target - now); |
1203 | 1205 |
1204 base::TimeDelta time = intervals * vsync_interval_; | 1206 base::TimeDelta time = intervals * vsync_interval_; |
1205 if (!callback_.is_null()) { | 1207 if (!callback_.is_null()) { |
1206 SendVSync(time, base::ResetAndReturn(&callback_)); | 1208 SendVSync(time, base::ResetAndReturn(&callback_)); |
1207 } else { | 1209 } else { |
1208 pending_vsync_ = true; | 1210 pending_vsync_ = true; |
1209 pending_time_ = time; | 1211 pending_time_ = time; |
1210 } | 1212 } |
1211 if (!web_vr_mode_) { | 1213 if (!ShouldDrawWebVr()) { |
1212 DrawFrame(-1); | 1214 DrawFrame(-1); |
1213 } | 1215 } |
1214 } | 1216 } |
1215 | 1217 |
1216 void VrShellGl::OnRequest(device::mojom::VRVSyncProviderRequest request) { | 1218 void VrShellGl::OnRequest(device::mojom::VRVSyncProviderRequest request) { |
1217 binding_.Close(); | 1219 binding_.Close(); |
1218 binding_.Bind(std::move(request)); | 1220 binding_.Bind(std::move(request)); |
1219 } | 1221 } |
1220 | 1222 |
1221 void VrShellGl::GetVSync(const GetVSyncCallback& callback) { | 1223 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 | 1286 // appropriate recommended render resolution as the default size during |
1285 // InitializeGl. Revisit if the initialization order changes. | 1287 // InitializeGl. Revisit if the initialization order changes. |
1286 device::mojom::VRDisplayInfoPtr info = VrShell::CreateVRDisplayInfo( | 1288 device::mojom::VRDisplayInfoPtr info = VrShell::CreateVRDisplayInfo( |
1287 gvr_api_.get(), webvr_surface_size_, device_id); | 1289 gvr_api_.get(), webvr_surface_size_, device_id); |
1288 main_thread_task_runner_->PostTask( | 1290 main_thread_task_runner_->PostTask( |
1289 FROM_HERE, | 1291 FROM_HERE, |
1290 base::Bind(&RunVRDisplayInfoCallback, callback, base::Passed(&info))); | 1292 base::Bind(&RunVRDisplayInfoCallback, callback, base::Passed(&info))); |
1291 } | 1293 } |
1292 | 1294 |
1293 } // namespace vr_shell | 1295 } // namespace vr_shell |
OLD | NEW |