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 |