| 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 "base/android/jni_android.h" |
| 7 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
| 8 #include "base/metrics/histogram_macros.h" | 9 #include "base/metrics/histogram_macros.h" |
| 9 #include "base/threading/thread_task_runner_handle.h" | 10 #include "base/threading/thread_task_runner_handle.h" |
| 10 #include "chrome/browser/android/vr_shell/ui_elements.h" | 11 #include "chrome/browser/android/vr_shell/ui_elements.h" |
| 11 #include "chrome/browser/android/vr_shell/ui_scene.h" | 12 #include "chrome/browser/android/vr_shell/ui_scene.h" |
| 12 #include "chrome/browser/android/vr_shell/vr_controller.h" | 13 #include "chrome/browser/android/vr_shell/vr_controller.h" |
| 13 #include "chrome/browser/android/vr_shell/vr_gl_util.h" | 14 #include "chrome/browser/android/vr_shell/vr_gl_util.h" |
| 14 #include "chrome/browser/android/vr_shell/vr_input_manager.h" | 15 #include "chrome/browser/android/vr_shell/vr_input_manager.h" |
| 15 #include "chrome/browser/android/vr_shell/vr_math.h" | 16 #include "chrome/browser/android/vr_shell/vr_math.h" |
| 16 #include "chrome/browser/android/vr_shell/vr_shell.h" | 17 #include "chrome/browser/android/vr_shell/vr_shell.h" |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 VLOG(1) << "WebVR: reject decoded pose index " << (int)pixels[0] << | 167 VLOG(1) << "WebVR: reject decoded pose index " << (int)pixels[0] << |
| 167 ", bad magic number " << (int)pixels[1] << ", " << (int)pixels[2]; | 168 ", bad magic number " << (int)pixels[1] << ", " << (int)pixels[2]; |
| 168 return -1; | 169 return -1; |
| 169 } | 170 } |
| 170 | 171 |
| 171 int64_t TimeInMicroseconds() { | 172 int64_t TimeInMicroseconds() { |
| 172 return std::chrono::duration_cast<std::chrono::microseconds>( | 173 return std::chrono::duration_cast<std::chrono::microseconds>( |
| 173 std::chrono::steady_clock::now().time_since_epoch()).count(); | 174 std::chrono::steady_clock::now().time_since_epoch()).count(); |
| 174 } | 175 } |
| 175 | 176 |
| 177 void WaitForSwapAck(const base::Closure& callback, gfx::SwapResult result) { |
| 178 callback.Run(); |
| 179 } |
| 180 |
| 176 } // namespace | 181 } // namespace |
| 177 | 182 |
| 178 VrShellGl::VrShellGl( | 183 VrShellGl::VrShellGl( |
| 179 const base::WeakPtr<VrShell>& weak_vr_shell, | 184 const base::WeakPtr<VrShell>& weak_vr_shell, |
| 180 const base::WeakPtr<VrInputManager>& content_input_manager, | 185 const base::WeakPtr<VrInputManager>& content_input_manager, |
| 181 const base::WeakPtr<VrInputManager>& ui_input_manager, | 186 const base::WeakPtr<VrInputManager>& ui_input_manager, |
| 182 scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner, | 187 scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner, |
| 183 gvr_context* gvr_api, | 188 gvr_context* gvr_api, |
| 184 bool initially_web_vr) | 189 bool initially_web_vr, |
| 190 bool reprojected_rendering) |
| 185 : web_vr_mode_(initially_web_vr), | 191 : web_vr_mode_(initially_web_vr), |
| 192 surfaceless_rendering_(reprojected_rendering), |
| 186 task_runner_(base::ThreadTaskRunnerHandle::Get()), | 193 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 187 weak_vr_shell_(weak_vr_shell), | 194 weak_vr_shell_(weak_vr_shell), |
| 188 content_input_manager_(content_input_manager), | 195 content_input_manager_(content_input_manager), |
| 189 ui_input_manager_(ui_input_manager), | 196 ui_input_manager_(ui_input_manager), |
| 190 main_thread_task_runner_(std::move(main_thread_task_runner)), | 197 main_thread_task_runner_(std::move(main_thread_task_runner)), |
| 191 weak_ptr_factory_(this) { | 198 weak_ptr_factory_(this) { |
| 192 GvrInit(gvr_api); | 199 GvrInit(gvr_api); |
| 193 } | 200 } |
| 194 | 201 |
| 195 VrShellGl::~VrShellGl() { | 202 VrShellGl::~VrShellGl() { |
| 196 draw_task_.Cancel(); | 203 draw_task_.Cancel(); |
| 197 } | 204 } |
| 198 | 205 |
| 199 bool VrShellGl::Initialize() { | 206 void VrShellGl::Initialize() { |
| 200 if (!InitializeGl()) return false; | |
| 201 | |
| 202 gvr::Mat4f identity; | 207 gvr::Mat4f identity; |
| 203 SetIdentityM(identity); | 208 SetIdentityM(identity); |
| 204 webvr_head_pose_.resize(kPoseRingBufferSize, identity); | 209 webvr_head_pose_.resize(kPoseRingBufferSize, identity); |
| 205 webvr_head_pose_valid_.resize(kPoseRingBufferSize, false); | 210 webvr_head_pose_valid_.resize(kPoseRingBufferSize, false); |
| 206 | 211 |
| 207 draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this))); | |
| 208 | |
| 209 scene_.reset(new UiScene); | 212 scene_.reset(new UiScene); |
| 210 | 213 |
| 211 InitializeRenderer(); | 214 if (surfaceless_rendering_) { |
| 212 | 215 // If we're rendering surfaceless, we'll never get a java surface to render |
| 213 ScheduleNextDrawFrame(); | 216 // into, so we can initialize GL right away. |
| 214 return true; | 217 InitializeGl(nullptr); |
| 218 } |
| 215 } | 219 } |
| 216 | 220 |
| 217 bool VrShellGl::InitializeGl() { | 221 void VrShellGl::InitializeGl(gfx::AcceleratedWidget window) { |
| 222 CHECK(!ready_to_draw_); |
| 218 if (gl::GetGLImplementation() == gl::kGLImplementationNone && | 223 if (gl::GetGLImplementation() == gl::kGLImplementationNone && |
| 219 !gl::init::InitializeGLOneOff()) { | 224 !gl::init::InitializeGLOneOff()) { |
| 220 LOG(ERROR) << "gl::init::InitializeGLOneOff failed"; | 225 LOG(ERROR) << "gl::init::InitializeGLOneOff failed"; |
| 221 ForceExitVr(); | 226 ForceExitVr(); |
| 222 return false; | 227 return; |
| 223 } | 228 } |
| 224 surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size()); | 229 if (window) { |
| 230 CHECK(!surfaceless_rendering_); |
| 231 surface_ = gl::init::CreateViewGLSurface(window); |
| 232 } else { |
| 233 CHECK(surfaceless_rendering_); |
| 234 surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size()); |
| 235 } |
| 225 if (!surface_.get()) { | 236 if (!surface_.get()) { |
| 226 LOG(ERROR) << "gl::init::CreateOffscreenGLSurface failed"; | 237 LOG(ERROR) << "gl::init::CreateOffscreenGLSurface failed"; |
| 227 ForceExitVr(); | 238 ForceExitVr(); |
| 228 return false; | 239 return; |
| 229 } | 240 } |
| 230 context_ = gl::init::CreateGLContext(nullptr, surface_.get(), | 241 context_ = gl::init::CreateGLContext(nullptr, surface_.get(), |
| 231 gl::GLContextAttribs()); | 242 gl::GLContextAttribs()); |
| 232 if (!context_.get()) { | 243 if (!context_.get()) { |
| 233 LOG(ERROR) << "gl::init::CreateGLContext failed"; | 244 LOG(ERROR) << "gl::init::CreateGLContext failed"; |
| 234 ForceExitVr(); | 245 ForceExitVr(); |
| 235 return false; | 246 return; |
| 236 } | 247 } |
| 237 if (!context_->MakeCurrent(surface_.get())) { | 248 if (!context_->MakeCurrent(surface_.get())) { |
| 238 LOG(ERROR) << "gl::GLContext::MakeCurrent() failed"; | 249 LOG(ERROR) << "gl::GLContext::MakeCurrent() failed"; |
| 239 ForceExitVr(); | 250 ForceExitVr(); |
| 240 return false; | 251 return; |
| 241 } | 252 } |
| 242 | 253 |
| 243 // TODO(mthiesse): We don't appear to have a VSync provider ever here. This is | 254 // TODO(mthiesse): We don't appear to have a VSync provider ever here. This is |
| 244 // sort of okay, because the GVR swap chain will block if we render too fast, | 255 // sort of okay, because the GVR swap chain will block if we render too fast, |
| 245 // but we should address this properly. | 256 // but we should address this properly. |
| 246 if (surface_->GetVSyncProvider()) { | 257 if (surface_->GetVSyncProvider()) { |
| 247 surface_->GetVSyncProvider()->GetVSyncParameters(base::Bind( | 258 surface_->GetVSyncProvider()->GetVSyncParameters(base::Bind( |
| 248 &VrShellGl::UpdateVSyncParameters, weak_ptr_factory_.GetWeakPtr())); | 259 &VrShellGl::UpdateVSyncParameters, weak_ptr_factory_.GetWeakPtr())); |
| 249 } else { | 260 } else { |
| 250 LOG(ERROR) << "No VSync Provider"; | 261 LOG(ERROR) << "No VSync Provider"; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 266 | 277 |
| 267 content_surface_texture_->SetDefaultBufferSize( | 278 content_surface_texture_->SetDefaultBufferSize( |
| 268 content_tex_physical_size_.width, content_tex_physical_size_.height); | 279 content_tex_physical_size_.width, content_tex_physical_size_.height); |
| 269 ui_surface_texture_->SetDefaultBufferSize(ui_tex_physical_size_.width, | 280 ui_surface_texture_->SetDefaultBufferSize(ui_tex_physical_size_.width, |
| 270 ui_tex_physical_size_.height); | 281 ui_tex_physical_size_.height); |
| 271 | 282 |
| 272 main_thread_task_runner_->PostTask(FROM_HERE, base::Bind( | 283 main_thread_task_runner_->PostTask(FROM_HERE, base::Bind( |
| 273 &VrShell::SurfacesChanged, weak_vr_shell_, | 284 &VrShell::SurfacesChanged, weak_vr_shell_, |
| 274 content_surface_->j_surface().obj(), | 285 content_surface_->j_surface().obj(), |
| 275 ui_surface_->j_surface().obj())); | 286 ui_surface_->j_surface().obj())); |
| 276 return true; | 287 |
| 288 InitializeRenderer(); |
| 289 |
| 290 draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this))); |
| 291 ScheduleNextDrawFrame(); |
| 292 |
| 293 ready_to_draw_ = true; |
| 277 } | 294 } |
| 278 | 295 |
| 279 void VrShellGl::OnUIFrameAvailable() { | 296 void VrShellGl::OnUIFrameAvailable() { |
| 280 ui_surface_texture_->UpdateTexImage(); | 297 ui_surface_texture_->UpdateTexImage(); |
| 281 } | 298 } |
| 282 | 299 |
| 283 void VrShellGl::OnContentFrameAvailable() { | 300 void VrShellGl::OnContentFrameAvailable() { |
| 284 content_surface_texture_->UpdateTexImage(); | 301 content_surface_texture_->UpdateTexImage(); |
| 285 } | 302 } |
| 286 | 303 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 webvr_right_viewport_.get()); | 396 webvr_right_viewport_.get()); |
| 380 webvr_right_viewport_->SetSourceBufferIndex(kFramePrimaryBuffer); | 397 webvr_right_viewport_->SetSourceBufferIndex(kFramePrimaryBuffer); |
| 381 | 398 |
| 382 main_thread_task_runner_->PostTask(FROM_HERE, base::Bind( | 399 main_thread_task_runner_->PostTask(FROM_HERE, base::Bind( |
| 383 &VrShell::GvrDelegateReady, weak_vr_shell_)); | 400 &VrShell::GvrDelegateReady, weak_vr_shell_)); |
| 384 } | 401 } |
| 385 | 402 |
| 386 void VrShellGl::UpdateController(const gvr::Vec3f& forward_vector) { | 403 void VrShellGl::UpdateController(const gvr::Vec3f& forward_vector) { |
| 387 controller_->UpdateState(); | 404 controller_->UpdateState(); |
| 388 | 405 |
| 389 | |
| 390 // Note that button up/down state is transient, so ButtonUpHappened only | 406 // Note that button up/down state is transient, so ButtonUpHappened only |
| 391 // returns true for a single frame (and we're guaranteed not to miss it). | 407 // returns true for a single frame (and we're guaranteed not to miss it). |
| 392 if (controller_->ButtonUpHappened( | 408 if (controller_->ButtonUpHappened( |
| 393 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_APP)) { | 409 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_APP)) { |
| 394 main_thread_task_runner_->PostTask( | 410 main_thread_task_runner_->PostTask( |
| 395 FROM_HERE, base::Bind(&VrShell::AppButtonPressed, weak_vr_shell_)); | 411 FROM_HERE, base::Bind(&VrShell::AppButtonPressed, weak_vr_shell_)); |
| 396 } | 412 } |
| 397 | 413 |
| 398 if (web_vr_mode_) { | 414 if (web_vr_mode_) { |
| 399 // Process screen touch events for Cardboard button compatibility. | 415 // Process screen touch events for Cardboard button compatibility. |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 webvr_right_viewport_->SetReprojection(GVR_REPROJECTION_NONE); | 673 webvr_right_viewport_->SetReprojection(GVR_REPROJECTION_NONE); |
| 658 } | 674 } |
| 659 } | 675 } |
| 660 } | 676 } |
| 661 | 677 |
| 662 DrawVrShell(head_pose, frame); | 678 DrawVrShell(head_pose, frame); |
| 663 | 679 |
| 664 frame.Unbind(); | 680 frame.Unbind(); |
| 665 frame.Submit(*buffer_viewport_list_, head_pose); | 681 frame.Submit(*buffer_viewport_list_, head_pose); |
| 666 | 682 |
| 667 // No need to SwapBuffers for an offscreen surface. | 683 // No need to swap buffers for surfaceless rendering. |
| 668 ScheduleNextDrawFrame(); | 684 if (surfaceless_rendering_) { |
| 685 ScheduleNextDrawFrame(); |
| 686 return; |
| 687 } |
| 688 |
| 689 if (surface_->SupportsAsyncSwap()) { |
| 690 surface_->SwapBuffersAsync(base::Bind(&WaitForSwapAck, base::Bind( |
| 691 &VrShellGl::ScheduleNextDrawFrame, weak_ptr_factory_.GetWeakPtr()))); |
| 692 } else { |
| 693 surface_->SwapBuffers(); |
| 694 ScheduleNextDrawFrame(); |
| 695 } |
| 669 } | 696 } |
| 670 | 697 |
| 671 void VrShellGl::DrawVrShell(const gvr::Mat4f& head_pose, | 698 void VrShellGl::DrawVrShell(const gvr::Mat4f& head_pose, |
| 672 gvr::Frame &frame) { | 699 gvr::Frame &frame) { |
| 673 TRACE_EVENT0("gpu", "VrShellGl::DrawVrShell"); | 700 TRACE_EVENT0("gpu", "VrShellGl::DrawVrShell"); |
| 674 std::vector<const ContentRectangle*> head_locked_elements; | 701 std::vector<const ContentRectangle*> head_locked_elements; |
| 675 std::vector<const ContentRectangle*> world_elements; | 702 std::vector<const ContentRectangle*> world_elements; |
| 676 for (const auto& rect : scene_->GetUiElements()) { | 703 for (const auto& rect : scene_->GetUiElements()) { |
| 677 if (!rect->visible) { | 704 if (!rect->visible) { |
| 678 continue; | 705 continue; |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 890 void VrShellGl::OnPause() { | 917 void VrShellGl::OnPause() { |
| 891 draw_task_.Cancel(); | 918 draw_task_.Cancel(); |
| 892 controller_->OnPause(); | 919 controller_->OnPause(); |
| 893 gvr_api_->PauseTracking(); | 920 gvr_api_->PauseTracking(); |
| 894 } | 921 } |
| 895 | 922 |
| 896 void VrShellGl::OnResume() { | 923 void VrShellGl::OnResume() { |
| 897 gvr_api_->RefreshViewerProfile(); | 924 gvr_api_->RefreshViewerProfile(); |
| 898 gvr_api_->ResumeTracking(); | 925 gvr_api_->ResumeTracking(); |
| 899 controller_->OnResume(); | 926 controller_->OnResume(); |
| 900 draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this))); | 927 if (ready_to_draw_) { |
| 901 ScheduleNextDrawFrame(); | 928 draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this))); |
| 929 ScheduleNextDrawFrame(); |
| 930 } |
| 902 } | 931 } |
| 903 | 932 |
| 904 void VrShellGl::SetWebVrMode(bool enabled) { | 933 void VrShellGl::SetWebVrMode(bool enabled) { |
| 905 web_vr_mode_ = enabled; | 934 web_vr_mode_ = enabled; |
| 906 } | 935 } |
| 907 | 936 |
| 908 void VrShellGl::UpdateWebVRTextureBounds(const gvr::Rectf& left_bounds, | 937 void VrShellGl::UpdateWebVRTextureBounds(const gvr::Rectf& left_bounds, |
| 909 const gvr::Rectf& right_bounds) { | 938 const gvr::Rectf& right_bounds) { |
| 910 webvr_left_viewport_->SetSourceUv(left_bounds); | 939 webvr_left_viewport_->SetSourceUv(left_bounds); |
| 911 webvr_right_viewport_->SetSourceUv(right_bounds); | 940 webvr_right_viewport_->SetSourceUv(right_bounds); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 968 void VrShellGl::ForceExitVr() { | 997 void VrShellGl::ForceExitVr() { |
| 969 main_thread_task_runner_->PostTask( | 998 main_thread_task_runner_->PostTask( |
| 970 FROM_HERE, base::Bind(&VrShell::ForceExitVr, weak_vr_shell_)); | 999 FROM_HERE, base::Bind(&VrShell::ForceExitVr, weak_vr_shell_)); |
| 971 } | 1000 } |
| 972 | 1001 |
| 973 void VrShellGl::UpdateScene(std::unique_ptr<base::ListValue> commands) { | 1002 void VrShellGl::UpdateScene(std::unique_ptr<base::ListValue> commands) { |
| 974 scene_->HandleCommands(std::move(commands), TimeInMicroseconds()); | 1003 scene_->HandleCommands(std::move(commands), TimeInMicroseconds()); |
| 975 } | 1004 } |
| 976 | 1005 |
| 977 } // namespace vr_shell | 1006 } // namespace vr_shell |
| OLD | NEW |