Chromium Code Reviews| 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_); | |
|
bshe
2017/01/04 16:40:23
optional nit: rename to gl_initialized_?
mthiesse
2017/01/04 16:58:09
I think ready_to_draw_ is clearer. GL being initia
| |
| 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; | |
| 294 | |
| 295 return; | |
|
bshe
2017/01/04 16:40:23
nit: remove return
mthiesse
2017/01/04 16:58:09
Done.
| |
| 277 } | 296 } |
| 278 | 297 |
| 279 void VrShellGl::OnUIFrameAvailable() { | 298 void VrShellGl::OnUIFrameAvailable() { |
| 280 ui_surface_texture_->UpdateTexImage(); | 299 ui_surface_texture_->UpdateTexImage(); |
| 281 } | 300 } |
| 282 | 301 |
| 283 void VrShellGl::OnContentFrameAvailable() { | 302 void VrShellGl::OnContentFrameAvailable() { |
| 284 content_surface_texture_->UpdateTexImage(); | 303 content_surface_texture_->UpdateTexImage(); |
| 285 } | 304 } |
| 286 | 305 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 379 webvr_right_viewport_.get()); | 398 webvr_right_viewport_.get()); |
| 380 webvr_right_viewport_->SetSourceBufferIndex(kFramePrimaryBuffer); | 399 webvr_right_viewport_->SetSourceBufferIndex(kFramePrimaryBuffer); |
| 381 | 400 |
| 382 main_thread_task_runner_->PostTask(FROM_HERE, base::Bind( | 401 main_thread_task_runner_->PostTask(FROM_HERE, base::Bind( |
| 383 &VrShell::GvrDelegateReady, weak_vr_shell_)); | 402 &VrShell::GvrDelegateReady, weak_vr_shell_)); |
| 384 } | 403 } |
| 385 | 404 |
| 386 void VrShellGl::UpdateController(const gvr::Vec3f& forward_vector) { | 405 void VrShellGl::UpdateController(const gvr::Vec3f& forward_vector) { |
| 387 controller_->UpdateState(); | 406 controller_->UpdateState(); |
| 388 | 407 |
| 389 | |
| 390 // Note that button up/down state is transient, so ButtonUpHappened only | 408 // 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). | 409 // returns true for a single frame (and we're guaranteed not to miss it). |
| 392 if (controller_->ButtonUpHappened( | 410 if (controller_->ButtonUpHappened( |
| 393 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_APP)) { | 411 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_APP)) { |
| 394 main_thread_task_runner_->PostTask( | 412 main_thread_task_runner_->PostTask( |
| 395 FROM_HERE, base::Bind(&VrShell::AppButtonPressed, weak_vr_shell_)); | 413 FROM_HERE, base::Bind(&VrShell::AppButtonPressed, weak_vr_shell_)); |
| 396 } | 414 } |
| 397 | 415 |
| 398 if (web_vr_mode_) { | 416 if (web_vr_mode_) { |
| 399 // Process screen touch events for Cardboard button compatibility. | 417 // 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); | 675 webvr_right_viewport_->SetReprojection(GVR_REPROJECTION_NONE); |
| 658 } | 676 } |
| 659 } | 677 } |
| 660 } | 678 } |
| 661 | 679 |
| 662 DrawVrShell(head_pose, frame); | 680 DrawVrShell(head_pose, frame); |
| 663 | 681 |
| 664 frame.Unbind(); | 682 frame.Unbind(); |
| 665 frame.Submit(*buffer_viewport_list_, head_pose); | 683 frame.Submit(*buffer_viewport_list_, head_pose); |
| 666 | 684 |
| 667 // No need to SwapBuffers for an offscreen surface. | 685 // No need to swap buffers for surfaceless rendering. |
| 668 ScheduleNextDrawFrame(); | 686 if (surfaceless_rendering_) { |
| 687 ScheduleNextDrawFrame(); | |
| 688 return; | |
| 689 } | |
| 690 | |
| 691 if (surface_->SupportsAsyncSwap()) { | |
| 692 surface_->SwapBuffersAsync(base::Bind(&WaitForSwapAck, base::Bind( | |
| 693 &VrShellGl::ScheduleNextDrawFrame, weak_ptr_factory_.GetWeakPtr()))); | |
| 694 } else { | |
| 695 surface_->SwapBuffers(); | |
| 696 ScheduleNextDrawFrame(); | |
| 697 } | |
| 669 } | 698 } |
| 670 | 699 |
| 671 void VrShellGl::DrawVrShell(const gvr::Mat4f& head_pose, | 700 void VrShellGl::DrawVrShell(const gvr::Mat4f& head_pose, |
| 672 gvr::Frame &frame) { | 701 gvr::Frame &frame) { |
| 673 TRACE_EVENT0("gpu", "VrShellGl::DrawVrShell"); | 702 TRACE_EVENT0("gpu", "VrShellGl::DrawVrShell"); |
| 674 std::vector<const ContentRectangle*> head_locked_elements; | 703 std::vector<const ContentRectangle*> head_locked_elements; |
| 675 std::vector<const ContentRectangle*> world_elements; | 704 std::vector<const ContentRectangle*> world_elements; |
| 676 for (const auto& rect : scene_->GetUiElements()) { | 705 for (const auto& rect : scene_->GetUiElements()) { |
| 677 if (!rect->visible) { | 706 if (!rect->visible) { |
| 678 continue; | 707 continue; |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 890 void VrShellGl::OnPause() { | 919 void VrShellGl::OnPause() { |
| 891 draw_task_.Cancel(); | 920 draw_task_.Cancel(); |
| 892 controller_->OnPause(); | 921 controller_->OnPause(); |
| 893 gvr_api_->PauseTracking(); | 922 gvr_api_->PauseTracking(); |
| 894 } | 923 } |
| 895 | 924 |
| 896 void VrShellGl::OnResume() { | 925 void VrShellGl::OnResume() { |
| 897 gvr_api_->RefreshViewerProfile(); | 926 gvr_api_->RefreshViewerProfile(); |
| 898 gvr_api_->ResumeTracking(); | 927 gvr_api_->ResumeTracking(); |
| 899 controller_->OnResume(); | 928 controller_->OnResume(); |
| 900 draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this))); | 929 if (ready_to_draw_) { |
| 901 ScheduleNextDrawFrame(); | 930 draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this))); |
| 931 ScheduleNextDrawFrame(); | |
| 932 } | |
| 902 } | 933 } |
| 903 | 934 |
| 904 void VrShellGl::SetWebVrMode(bool enabled) { | 935 void VrShellGl::SetWebVrMode(bool enabled) { |
| 905 web_vr_mode_ = enabled; | 936 web_vr_mode_ = enabled; |
| 906 } | 937 } |
| 907 | 938 |
| 908 void VrShellGl::UpdateWebVRTextureBounds(const gvr::Rectf& left_bounds, | 939 void VrShellGl::UpdateWebVRTextureBounds(const gvr::Rectf& left_bounds, |
| 909 const gvr::Rectf& right_bounds) { | 940 const gvr::Rectf& right_bounds) { |
| 910 webvr_left_viewport_->SetSourceUv(left_bounds); | 941 webvr_left_viewport_->SetSourceUv(left_bounds); |
| 911 webvr_right_viewport_->SetSourceUv(right_bounds); | 942 webvr_right_viewport_->SetSourceUv(right_bounds); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 968 void VrShellGl::ForceExitVr() { | 999 void VrShellGl::ForceExitVr() { |
| 969 main_thread_task_runner_->PostTask( | 1000 main_thread_task_runner_->PostTask( |
| 970 FROM_HERE, base::Bind(&VrShell::ForceExitVr, weak_vr_shell_)); | 1001 FROM_HERE, base::Bind(&VrShell::ForceExitVr, weak_vr_shell_)); |
| 971 } | 1002 } |
| 972 | 1003 |
| 973 void VrShellGl::UpdateScene(std::unique_ptr<base::ListValue> commands) { | 1004 void VrShellGl::UpdateScene(std::unique_ptr<base::ListValue> commands) { |
| 974 scene_->HandleCommands(std::move(commands), TimeInMicroseconds()); | 1005 scene_->HandleCommands(std::move(commands), TimeInMicroseconds()); |
| 975 } | 1006 } |
| 976 | 1007 |
| 977 } // namespace vr_shell | 1008 } // namespace vr_shell |
| OLD | NEW |