Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(233)

Side by Side Diff: chrome/browser/android/vr_shell/vr_shell_gl.cc

Issue 2729523002: Re-land^2 WebVR compositor bypass via BrowserMain context + mailbox (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 12 matching lines...) Expand all
23 #include "device/vr/android/gvr/gvr_device.h" 23 #include "device/vr/android/gvr/gvr_device.h"
24 #include "third_party/WebKit/public/platform/WebInputEvent.h" 24 #include "third_party/WebKit/public/platform/WebInputEvent.h"
25 #include "third_party/WebKit/public/platform/WebMouseEvent.h" 25 #include "third_party/WebKit/public/platform/WebMouseEvent.h"
26 #include "ui/gl/android/scoped_java_surface.h" 26 #include "ui/gl/android/scoped_java_surface.h"
27 #include "ui/gl/android/surface_texture.h" 27 #include "ui/gl/android/surface_texture.h"
28 #include "ui/gl/gl_bindings.h" 28 #include "ui/gl/gl_bindings.h"
29 #include "ui/gl/gl_context.h" 29 #include "ui/gl/gl_context.h"
30 #include "ui/gl/gl_surface.h" 30 #include "ui/gl/gl_surface.h"
31 #include "ui/gl/init/gl_factory.h" 31 #include "ui/gl/init/gl_factory.h"
32 32
33 #include "gpu/ipc/common/gpu_surface_tracker.h"
34
33 namespace vr_shell { 35 namespace vr_shell {
34 36
35 namespace { 37 namespace {
36 // TODO(mthiesse): If gvr::PlatformInfo().GetPosePredictionTime() is ever 38 // TODO(mthiesse): If gvr::PlatformInfo().GetPosePredictionTime() is ever
37 // exposed, use that instead (it defaults to 50ms on most platforms). 39 // exposed, use that instead (it defaults to 50ms on most platforms).
38 static constexpr int64_t kPredictionTimeWithoutVsyncNanos = 50000000; 40 static constexpr int64_t kPredictionTimeWithoutVsyncNanos = 50000000;
39 41
40 static constexpr float kZNear = 0.1f; 42 static constexpr float kZNear = 0.1f;
41 static constexpr float kZFar = 1000.0f; 43 static constexpr float kZFar = 1000.0f;
42 44
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 78
77 // The GVR viewport list has two entries (left eye and right eye) for each 79 // The GVR viewport list has two entries (left eye and right eye) for each
78 // GVR buffer. 80 // GVR buffer.
79 static constexpr int kViewportListPrimaryOffset = 0; 81 static constexpr int kViewportListPrimaryOffset = 0;
80 static constexpr int kViewportListHeadlockedOffset = 2; 82 static constexpr int kViewportListHeadlockedOffset = 2;
81 83
82 // Buffer size large enough to handle the current backlog of poses which is 84 // Buffer size large enough to handle the current backlog of poses which is
83 // 2-3 frames. 85 // 2-3 frames.
84 static constexpr unsigned kPoseRingBufferSize = 8; 86 static constexpr unsigned kPoseRingBufferSize = 8;
85 87
88 #if 0
86 // Magic numbers used to mark valid pose index values encoded in frame 89 // Magic numbers used to mark valid pose index values encoded in frame
87 // data. Must match the magic numbers used in blink's VRDisplay.cpp. 90 // data. Must match the magic numbers used in blink's VRDisplay.cpp.
88 static constexpr std::array<uint8_t, 2> kWebVrPosePixelMagicNumbers{{42, 142}}; 91 static constexpr std::array<uint8_t, 2> kWebVrPosePixelMagicNumbers{{42, 142}};
92 #endif
89 93
90 float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) { 94 float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) {
91 float xdiff = (vec1.x - vec2.x); 95 float xdiff = (vec1.x - vec2.x);
92 float ydiff = (vec1.y - vec2.y); 96 float ydiff = (vec1.y - vec2.y);
93 float zdiff = (vec1.z - vec2.z); 97 float zdiff = (vec1.z - vec2.z);
94 float scale = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff; 98 float scale = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff;
95 return std::sqrt(scale); 99 return std::sqrt(scale);
96 } 100 }
97 101
98 // Generate a quaternion representing the rotation from the negative Z axis 102 // Generate a quaternion representing the rotation from the negative Z axis
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 LOG(ERROR) << "gl::init::CreateGLContext failed"; 232 LOG(ERROR) << "gl::init::CreateGLContext failed";
229 ForceExitVr(); 233 ForceExitVr();
230 return; 234 return;
231 } 235 }
232 if (!context_->MakeCurrent(surface_.get())) { 236 if (!context_->MakeCurrent(surface_.get())) {
233 LOG(ERROR) << "gl::GLContext::MakeCurrent() failed"; 237 LOG(ERROR) << "gl::GLContext::MakeCurrent() failed";
234 ForceExitVr(); 238 ForceExitVr();
235 return; 239 return;
236 } 240 }
237 241
238 unsigned int textures[2]; 242 unsigned int textures[3];
239 glGenTextures(2, textures); 243 glGenTextures(3, textures);
240 ui_texture_id_ = textures[0]; 244 ui_texture_id_ = textures[0];
241 content_texture_id_ = textures[1]; 245 content_texture_id_ = textures[1];
246 webvr_texture_id_ = textures[2];
242 ui_surface_texture_ = gl::SurfaceTexture::Create(ui_texture_id_); 247 ui_surface_texture_ = gl::SurfaceTexture::Create(ui_texture_id_);
243 content_surface_texture_ = gl::SurfaceTexture::Create(content_texture_id_); 248 content_surface_texture_ = gl::SurfaceTexture::Create(content_texture_id_);
249 webvr_surface_texture_ = gl::SurfaceTexture::Create(webvr_texture_id_);
244 CreateUiSurface(); 250 CreateUiSurface();
245 CreateContentSurface(); 251 CreateContentSurface();
252 CreateWebVRSurface();
246 ui_surface_texture_->SetFrameAvailableCallback(base::Bind( 253 ui_surface_texture_->SetFrameAvailableCallback(base::Bind(
247 &VrShellGl::OnUIFrameAvailable, weak_ptr_factory_.GetWeakPtr())); 254 &VrShellGl::OnUIFrameAvailable, weak_ptr_factory_.GetWeakPtr()));
248 content_surface_texture_->SetFrameAvailableCallback(base::Bind( 255 content_surface_texture_->SetFrameAvailableCallback(base::Bind(
249 &VrShellGl::OnContentFrameAvailable, weak_ptr_factory_.GetWeakPtr())); 256 &VrShellGl::OnContentFrameAvailable, weak_ptr_factory_.GetWeakPtr()));
257 webvr_surface_texture_->SetFrameAvailableCallback(base::Bind(
258 &VrShellGl::OnWebVRFrameAvailable, weak_ptr_factory_.GetWeakPtr()));
259 ui_surface_texture_->SetDefaultBufferSize(ui_tex_physical_size_.width,
260 ui_tex_physical_size_.height);
250 content_surface_texture_->SetDefaultBufferSize( 261 content_surface_texture_->SetDefaultBufferSize(
251 content_tex_physical_size_.width, content_tex_physical_size_.height); 262 content_tex_physical_size_.width, content_tex_physical_size_.height);
252 ui_surface_texture_->SetDefaultBufferSize(ui_tex_physical_size_.width, 263 VLOG(1) << __FUNCTION__ << ";;; content_tex_physical_size=" <<
253 ui_tex_physical_size_.height); 264 content_tex_physical_size_.width << "x" <<
265 content_tex_physical_size_.height;
266 VLOG(1) << __FUNCTION__ << ";;; render_size_primary=" <<
267 render_size_primary_.width << "x" << render_size_primary_.height;
268 webvr_surface_texture_->SetDefaultBufferSize(
269 //content_tex_physical_size_.width, content_tex_physical_size_.height);
270 2560, 1440); // FIXME!
254 InitializeRenderer(); 271 InitializeRenderer();
255 272
256 vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this))); 273 vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this)));
257 OnVSync(); 274 OnVSync();
258 275
259 ready_to_draw_ = true; 276 ready_to_draw_ = true;
260 } 277 }
261 278
262 void VrShellGl::CreateContentSurface() { 279 void VrShellGl::CreateContentSurface() {
263 content_surface_ = 280 content_surface_ =
264 base::MakeUnique<gl::ScopedJavaSurface>(content_surface_texture_.get()); 281 base::MakeUnique<gl::ScopedJavaSurface>(content_surface_texture_.get());
265 main_thread_task_runner_->PostTask( 282 main_thread_task_runner_->PostTask(
266 FROM_HERE, base::Bind(&VrShell::ContentSurfaceChanged, weak_vr_shell_, 283 FROM_HERE, base::Bind(&VrShell::ContentSurfaceChanged, weak_vr_shell_,
267 content_surface_->j_surface().obj())); 284 content_surface_->j_surface().obj()));
268 } 285 }
269 286
270 void VrShellGl::CreateUiSurface() { 287 void VrShellGl::CreateUiSurface() {
271 ui_surface_ = 288 ui_surface_ =
272 base::MakeUnique<gl::ScopedJavaSurface>(ui_surface_texture_.get()); 289 base::MakeUnique<gl::ScopedJavaSurface>(ui_surface_texture_.get());
273 main_thread_task_runner_->PostTask( 290 main_thread_task_runner_->PostTask(
274 FROM_HERE, base::Bind(&VrShell::UiSurfaceChanged, weak_vr_shell_, 291 FROM_HERE, base::Bind(&VrShell::UiSurfaceChanged, weak_vr_shell_,
275 ui_surface_->j_surface().obj())); 292 ui_surface_->j_surface().obj()));
276 } 293 }
277 294
295 void VrShellGl::CreateWebVRSurface() {
296 ANativeWindow* window = webvr_surface_texture_->CreateSurface();
297 gpu::GpuSurfaceTracker* tracker = gpu::GpuSurfaceTracker::Get();
298 ANativeWindow_acquire(window);
299 // setBuffersGeometry seems optional, it uses the SurfaceTexture's
300 // default size by default?
301 // ANativeWindow_setBuffersGeometry(
302 // window, 2048, 1024, WINDOW_FORMAT_RGBA_8888); // FIXME!
303 webvr_surface_handle_ = tracker->AddSurfaceForNativeWidget(window);
304 VLOG(1) << __FUNCTION__ << ";;;: webvr_surface_handle_=" <<
305 webvr_surface_handle_;
306
307 webvr_surface_ =
308 base::MakeUnique<gl::ScopedJavaSurface>(webvr_surface_texture_.get());
309 tracker->RegisterViewSurface(
310 webvr_surface_handle_, webvr_surface_->j_surface().obj());
311 // When should this be released? Does registering it keep it alive?
312 ANativeWindow_release(window);
313
314 main_thread_task_runner_->PostTask(
315 FROM_HERE, base::Bind(&VrShell::WebVRSurfaceChanged, weak_vr_shell_,
316 webvr_surface_handle_));
317 }
318
278 void VrShellGl::OnUIFrameAvailable() { 319 void VrShellGl::OnUIFrameAvailable() {
320 VLOG(1) << __FUNCTION__ << ";;; UI UpdateTexImage start";
279 ui_surface_texture_->UpdateTexImage(); 321 ui_surface_texture_->UpdateTexImage();
322 VLOG(1) << __FUNCTION__ << ";;; UI UpdateTexImage end";
280 } 323 }
281 324
282 void VrShellGl::OnContentFrameAvailable() { 325 void VrShellGl::OnContentFrameAvailable() {
326 VLOG(1) << __FUNCTION__ << ";;; Content UpdateTexImage start";
283 content_surface_texture_->UpdateTexImage(); 327 content_surface_texture_->UpdateTexImage();
284 received_frame_ = true; 328 received_frame_ = true;
329 VLOG(1) << __FUNCTION__ << ";;; Content UpdateTexImage end";
285 } 330 }
286 331
332 void VrShellGl::OnWebVRFrameAvailable() {
333 VLOG(1) << __FUNCTION__ << ";;; pending count=" << pending_frames_.size();
334 // A "while" loop here is a bad idea. It's legal to call
335 // UpdateTexImage repeatedly even if no frames are available, but
336 // that does *not* wait for a new frame, it just reuses the most
337 // recent one. That would mess up the count.
338 if (pending_frames_.empty()) {
339 VLOG(1) << __FUNCTION__ << ";;; no pending frames? Please retry! premature_r eceived_frames " << premature_received_frames_ << " => " << (premature_received_ frames_ + 1);
340 ++premature_received_frames_;
341 return;
342 }
343
344 VLOG(1) << __FUNCTION__ << ";;; requested_frames " << requested_frames_ << " = > " << (requested_frames_ - 1);
345 --requested_frames_;
346 VLOG(1) << __FUNCTION__ << ";;; WebVR UpdateTexImage start";
347 webvr_surface_texture_->UpdateTexImage();
348 int frame_index = pending_frames_.front();
349 pending_frames_.pop();
350 VLOG(1) << __FUNCTION__ << ";;; WebVR UpdateTexImage end, got frame=" << frame _index;
351 DrawFrame(frame_index);
352 main_thread_task_runner_->PostTask(
353 FROM_HERE, base::Bind(&VrShell::WebVRFrameCompleted, weak_vr_shell_,
354 frame_index));
355
356 if (pending_frames_.empty() && requested_frames_ > 0) {
357 // Heuristic got confused? TODO(klausw): do proper SubmitFrame callback?
358 VLOG(1) << __FUNCTION__ << ";;; Resetting requested_frames " << requested_fr ames_ << " => " << 0;
359 requested_frames_ = 0;
360 }
361 }
362
363 #if 0
287 bool VrShellGl::GetPixelEncodedFrameIndex(uint16_t* frame_index) { 364 bool VrShellGl::GetPixelEncodedFrameIndex(uint16_t* frame_index) {
365 //*frame_index = 1;
366 //return true;
288 TRACE_EVENT0("gpu", "VrShellGl::GetPixelEncodedFrameIndex"); 367 TRACE_EVENT0("gpu", "VrShellGl::GetPixelEncodedFrameIndex");
289 if (!received_frame_) { 368 if (!received_frame_) {
290 if (last_frame_index_ == (uint16_t)-1) 369 if (last_frame_index_ == (uint16_t)-1)
291 return false; 370 return false;
292 *frame_index = last_frame_index_; 371 *frame_index = last_frame_index_;
293 return true; 372 return true;
294 } 373 }
295 received_frame_ = false; 374 received_frame_ = false;
296 375
297 // Read the pose index encoded in a bottom left pixel as color values. 376 // Read the pose index encoded in a bottom left pixel as color values.
(...skipping 16 matching lines...) Expand all
314 // Pose is good. 393 // Pose is good.
315 *frame_index = pixels[0]; 394 *frame_index = pixels[0];
316 last_frame_index_ = pixels[0]; 395 last_frame_index_ = pixels[0];
317 return true; 396 return true;
318 } 397 }
319 VLOG(1) << "WebVR: reject decoded pose index " << static_cast<int>(pixels[0]) 398 VLOG(1) << "WebVR: reject decoded pose index " << static_cast<int>(pixels[0])
320 << ", bad magic number " << static_cast<int>(pixels[1]) << ", " 399 << ", bad magic number " << static_cast<int>(pixels[1]) << ", "
321 << static_cast<int>(pixels[2]); 400 << static_cast<int>(pixels[2]);
322 return false; 401 return false;
323 } 402 }
403 #endif
324 404
325 void VrShellGl::GvrInit(gvr_context* gvr_api) { 405 void VrShellGl::GvrInit(gvr_context* gvr_api) {
326 gvr_api_ = gvr::GvrApi::WrapNonOwned(gvr_api); 406 gvr_api_ = gvr::GvrApi::WrapNonOwned(gvr_api);
327 controller_.reset(new VrController(gvr_api)); 407 controller_.reset(new VrController(gvr_api));
328 408
329 ViewerType viewerType; 409 ViewerType viewerType;
330 switch (gvr_api_->GetViewerType()) { 410 switch (gvr_api_->GetViewerType()) {
331 case gvr::ViewerType::GVR_VIEWER_TYPE_DAYDREAM: 411 case gvr::ViewerType::GVR_VIEWER_TYPE_DAYDREAM:
332 viewerType = ViewerType::DAYDREAM; 412 viewerType = ViewerType::DAYDREAM;
333 break; 413 break;
334 case gvr::ViewerType::GVR_VIEWER_TYPE_CARDBOARD: 414 case gvr::ViewerType::GVR_VIEWER_TYPE_CARDBOARD:
335 viewerType = ViewerType::CARDBOARD; 415 viewerType = ViewerType::CARDBOARD;
336 break; 416 break;
337 default: 417 default:
338 NOTREACHED(); 418 NOTREACHED();
339 viewerType = ViewerType::UNKNOWN_TYPE; 419 viewerType = ViewerType::UNKNOWN_TYPE;
340 break; 420 break;
341 } 421 }
342 UMA_HISTOGRAM_ENUMERATION("VRViewerType", static_cast<int>(viewerType), 422 UMA_HISTOGRAM_ENUMERATION("VRViewerType", static_cast<int>(viewerType),
343 static_cast<int>(ViewerType::VIEWER_TYPE_MAX)); 423 static_cast<int>(ViewerType::VIEWER_TYPE_MAX));
344 } 424 }
345 425
346 void VrShellGl::InitializeRenderer() { 426 void VrShellGl::InitializeRenderer() {
347 // While WebVR is going through the compositor path, it shares
348 // the same texture ID. This will change once it gets its own
349 // surface, but store it separately to avoid future confusion.
350 // TODO(klausw,crbug.com/655722): remove this.
351 webvr_texture_id_ = content_texture_id_;
352
353 gvr_api_->InitializeGl(); 427 gvr_api_->InitializeGl();
354 webvr_head_pose_.assign(kPoseRingBufferSize, 428 webvr_head_pose_.assign(kPoseRingBufferSize,
355 gvr_api_->GetHeadSpaceFromStartSpaceRotation( 429 gvr_api_->GetHeadSpaceFromStartSpaceRotation(
356 gvr::GvrApi::GetTimePointNow())); 430 gvr::GvrApi::GetTimePointNow()));
357 431
358 std::vector<gvr::BufferSpec> specs; 432 std::vector<gvr::BufferSpec> specs;
359 // For kFramePrimaryBuffer (primary VrShell and WebVR content) 433 // For kFramePrimaryBuffer (primary VrShell and WebVR content)
360 specs.push_back(gvr_api_->CreateBufferSpec()); 434 specs.push_back(gvr_api_->CreateBufferSpec());
361 render_size_primary_ = specs[kFramePrimaryBuffer].GetSize(); 435 render_size_primary_ = specs[kFramePrimaryBuffer].GetSize();
362 436
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 std::unique_ptr<blink::WebInputEvent> event) { 697 std::unique_ptr<blink::WebInputEvent> event) {
624 DCHECK(input_target != InputTarget::NONE); 698 DCHECK(input_target != InputTarget::NONE);
625 auto&& target = input_target == InputTarget::CONTENT 699 auto&& target = input_target == InputTarget::CONTENT
626 ? &VrShell::ProcessContentGesture 700 ? &VrShell::ProcessContentGesture
627 : &VrShell::ProcessUIGesture; 701 : &VrShell::ProcessUIGesture;
628 main_thread_task_runner_->PostTask( 702 main_thread_task_runner_->PostTask(
629 FROM_HERE, 703 FROM_HERE,
630 base::Bind(target, weak_vr_shell_, base::Passed(std::move(event)))); 704 base::Bind(target, weak_vr_shell_, base::Passed(std::move(event))));
631 } 705 }
632 706
633 void VrShellGl::DrawFrame() { 707 void VrShellGl::DrawFrame(int frame_index) {
634 TRACE_EVENT0("gpu", "VrShellGl::DrawFrame"); 708 TRACE_EVENT0("gpu", "VrShellGl::DrawFrame");
635 709
636 // Reset the viewport list to just the pair of viewports for the 710 // Reset the viewport list to just the pair of viewports for the
637 // primary buffer each frame. Head-locked viewports get added by 711 // primary buffer each frame. Head-locked viewports get added by
638 // DrawVrShell if needed. 712 // DrawVrShell if needed.
639 buffer_viewport_list_->SetToRecommendedBufferViewports(); 713 buffer_viewport_list_->SetToRecommendedBufferViewports();
640 714
715 TRACE_EVENT_BEGIN0("gpu", "VrShellGl::AcquireFrame");
641 gvr::Frame frame = swap_chain_->AcquireFrame(); 716 gvr::Frame frame = swap_chain_->AcquireFrame();
717 TRACE_EVENT_END0("gpu", "VrShellGl::AcquireFrame");
642 if (!frame.is_valid()) { 718 if (!frame.is_valid()) {
643 return; 719 return;
644 } 720 }
645 frame.BindBuffer(kFramePrimaryBuffer); 721 frame.BindBuffer(kFramePrimaryBuffer);
646 if (web_vr_mode_) { 722 if (web_vr_mode_) {
647 DrawWebVr(); 723 DrawWebVr();
648 } 724 }
649 725
650 uint16_t frame_index;
651 gvr::Mat4f head_pose; 726 gvr::Mat4f head_pose;
652 727
653 // When using async reprojection, we need to know which pose was used in 728 // When using async reprojection, we need to know which pose was used in
654 // the WebVR app for drawing this frame. Due to unknown amounts of 729 // the WebVR app for drawing this frame. Due to unknown amounts of
655 // buffering in the compositor and SurfaceTexture, we read the pose number 730 // buffering in the compositor and SurfaceTexture, we read the pose number
656 // from a corner pixel. There's no point in doing this for legacy 731 // from a corner pixel. There's no point in doing this for legacy
657 // distortion rendering since that doesn't need a pose, and reading back 732 // distortion rendering since that doesn't need a pose, and reading back
658 // pixels is an expensive operation. TODO(klausw,crbug.com/655722): stop 733 // pixels is an expensive operation. TODO(klausw,crbug.com/655722): stop
659 // doing this once we have working no-compositor rendering for WebVR. 734 // doing this once we have working no-compositor rendering for WebVR.
660 if (web_vr_mode_ && gvr_api_->GetAsyncReprojectionEnabled() && 735 if (web_vr_mode_ && gvr_api_->GetAsyncReprojectionEnabled()) {
661 GetPixelEncodedFrameIndex(&frame_index)) {
662 static_assert(!((kPoseRingBufferSize - 1) & kPoseRingBufferSize), 736 static_assert(!((kPoseRingBufferSize - 1) & kPoseRingBufferSize),
663 "kPoseRingBufferSize must be a power of 2"); 737 "kPoseRingBufferSize must be a power of 2");
664 head_pose = webvr_head_pose_[frame_index % kPoseRingBufferSize]; 738 head_pose = webvr_head_pose_[frame_index % kPoseRingBufferSize];
665 // Process all pending_bounds_ changes targeted for before this frame, being 739 // Process all pending_bounds_ changes targeted for before this frame, being
666 // careful of wrapping frame indices. 740 // careful of wrapping frame indices.
667 static constexpr unsigned max = 741 static constexpr unsigned max =
668 std::numeric_limits<decltype(frame_index_)>::max(); 742 std::numeric_limits<decltype(frame_index_)>::max();
669 static_assert(max > kPoseRingBufferSize * 2, 743 static_assert(max > kPoseRingBufferSize * 2,
670 "To detect wrapping, kPoseRingBufferSize must be smaller " 744 "To detect wrapping, kPoseRingBufferSize must be smaller "
671 "than half of frame_index_ range."); 745 "than half of frame_index_ range.");
672 while (!pending_bounds_.empty()) { 746 while (!pending_bounds_.empty()) {
673 uint16_t index = pending_bounds_.front().first; 747 uint16_t index = pending_bounds_.front().first;
748 VLOG(1) << __FUNCTION__ << ";;; new bounds, index=" << index;
674 // If index is less than the frame_index it's possible we've wrapped, so 749 // If index is less than the frame_index it's possible we've wrapped, so
675 // we extend the range and 'un-wrap' to account for this. 750 // we extend the range and 'un-wrap' to account for this.
676 if (index < frame_index) 751 if (index < frame_index)
677 index += max; 752 index += max;
678 // If the pending bounds change is for an upcoming frame within our buffer 753 // If the pending bounds change is for an upcoming frame within our buffer
679 // size, wait to apply it. Otherwise, apply it immediately. This 754 // size, wait to apply it. Otherwise, apply it immediately. This
680 // guarantees that even if we miss many frames, the queue can't fill up 755 // guarantees that even if we miss many frames, the queue can't fill up
681 // with stale bounds. 756 // with stale bounds.
682 if (index > frame_index && index <= frame_index + kPoseRingBufferSize) 757 if (index > frame_index && index <= frame_index + kPoseRingBufferSize)
683 break; 758 break;
(...skipping 22 matching lines...) Expand all
706 // it. For now, removing it seems working fine. 781 // it. For now, removing it seems working fine.
707 gvr_api_->ApplyNeckModel(head_pose, 1.0f); 782 gvr_api_->ApplyNeckModel(head_pose, 1.0f);
708 } 783 }
709 784
710 // Update the render position of all UI elements (including desktop). 785 // Update the render position of all UI elements (including desktop).
711 const float screen_tilt = kDesktopScreenTiltDefault * M_PI / 180.0f; 786 const float screen_tilt = kDesktopScreenTiltDefault * M_PI / 180.0f;
712 scene_->UpdateTransforms(screen_tilt, TimeInMicroseconds()); 787 scene_->UpdateTransforms(screen_tilt, TimeInMicroseconds());
713 788
714 UpdateController(GetForwardVector(head_pose)); 789 UpdateController(GetForwardVector(head_pose));
715 790
716 DrawVrShell(head_pose, frame); 791 // Drawing VrShell causes GL error 0x501 GL_INVALID_VALUE while in
792 // WebVR mode. FIXME.
793 if (!web_vr_mode_) DrawVrShell(head_pose, frame);
717 794
718 frame.Unbind(); 795 frame.Unbind();
719 frame.Submit(*buffer_viewport_list_, head_pose); 796 frame.Submit(*buffer_viewport_list_, head_pose);
720 797
721 // No need to swap buffers for surfaceless rendering. 798 // No need to swap buffers for surfaceless rendering.
722 if (!surfaceless_rendering_) { 799 if (!surfaceless_rendering_) {
723 // TODO(mthiesse): Support asynchronous SwapBuffers. 800 // TODO(mthiesse): Support asynchronous SwapBuffers.
724 surface_->SwapBuffers(); 801 surface_->SwapBuffers();
725 } 802 }
726 } 803 }
727 804
805 void VrShellGl::ScheduleWebVRFrame(int frame_index) {
806 VLOG(1) << __FUNCTION__ << ";;; schedule frame=" << frame_index;
807 pending_frames_.emplace(frame_index);
808 }
809
810 void VrShellGl::DropWebVRFrame(int frame_index) {
811 VLOG(1) << __FUNCTION__ << ";;; drop frame=" << frame_index;
812 if (requested_frames_ > 0) {
813 VLOG(1) << __FUNCTION__ << ";;; requested_frames " << requested_frames_ <<
814 " => " << (requested_frames_ - 1);
815 --requested_frames_;
816 }
817 }
818
728 void VrShellGl::DrawVrShell(const gvr::Mat4f& head_pose, gvr::Frame& frame) { 819 void VrShellGl::DrawVrShell(const gvr::Mat4f& head_pose, gvr::Frame& frame) {
729 TRACE_EVENT0("gpu", "VrShellGl::DrawVrShell"); 820 TRACE_EVENT0("gpu", "VrShellGl::DrawVrShell");
730 std::vector<const ContentRectangle*> head_locked_elements; 821 std::vector<const ContentRectangle*> head_locked_elements;
731 std::vector<const ContentRectangle*> world_elements; 822 std::vector<const ContentRectangle*> world_elements;
732 for (const auto& rect : scene_->GetUiElements()) { 823 for (const auto& rect : scene_->GetUiElements()) {
733 if (!rect->IsVisible()) 824 if (!rect->IsVisible())
734 continue; 825 continue;
735 if (rect->lock_to_fov) { 826 if (rect->lock_to_fov) {
736 head_locked_elements.push_back(rect.get()); 827 head_locked_elements.push_back(rect.get());
737 } else { 828 } else {
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
1022 } 1113 }
1023 } 1114 }
1024 1115
1025 void VrShellGl::SetWebVrMode(bool enabled) { 1116 void VrShellGl::SetWebVrMode(bool enabled) {
1026 web_vr_mode_ = enabled; 1117 web_vr_mode_ = enabled;
1027 } 1118 }
1028 1119
1029 void VrShellGl::UpdateWebVRTextureBounds(int16_t frame_index, 1120 void VrShellGl::UpdateWebVRTextureBounds(int16_t frame_index,
1030 const gvr::Rectf& left_bounds, 1121 const gvr::Rectf& left_bounds,
1031 const gvr::Rectf& right_bounds) { 1122 const gvr::Rectf& right_bounds) {
1123 VLOG(1) << __FUNCTION__ << ";;; frame_index=" << frame_index <<
1124 " left=" << left_bounds.left << "," << left_bounds.bottom <<
1125 "," << left_bounds.right << "," << left_bounds.top <<
1126 " right=" << right_bounds.left << "," << right_bounds.bottom <<
1127 "," << right_bounds.right << "," << right_bounds.top;
1032 if (frame_index < 0) { 1128 if (frame_index < 0) {
1033 webvr_left_viewport_->SetSourceUv(left_bounds); 1129 webvr_left_viewport_->SetSourceUv(left_bounds);
1034 webvr_right_viewport_->SetSourceUv(right_bounds); 1130 webvr_right_viewport_->SetSourceUv(right_bounds);
1035 } else { 1131 } else {
1036 pending_bounds_.emplace( 1132 pending_bounds_.emplace(
1037 std::make_pair(frame_index, std::make_pair(left_bounds, right_bounds))); 1133 std::make_pair(frame_index, std::make_pair(left_bounds, right_bounds)));
1038 } 1134 }
1039 } 1135 }
1040 1136
1041 void VrShellGl::ContentBoundsChanged(int width, int height) { 1137 void VrShellGl::ContentBoundsChanged(int width, int height) {
(...skipping 19 matching lines...) Expand all
1061 ui_surface_texture_->SetDefaultBufferSize(width, height); 1157 ui_surface_texture_->SetDefaultBufferSize(width, height);
1062 ui_tex_physical_size_.width = width; 1158 ui_tex_physical_size_.width = width;
1063 ui_tex_physical_size_.height = height; 1159 ui_tex_physical_size_.height = height;
1064 } 1160 }
1065 1161
1066 base::WeakPtr<VrShellGl> VrShellGl::GetWeakPtr() { 1162 base::WeakPtr<VrShellGl> VrShellGl::GetWeakPtr() {
1067 return weak_ptr_factory_.GetWeakPtr(); 1163 return weak_ptr_factory_.GetWeakPtr();
1068 } 1164 }
1069 1165
1070 void VrShellGl::OnVSync() { 1166 void VrShellGl::OnVSync() {
1167 while (premature_received_frames_ > 0) {
1168 VLOG(1) << __FUNCTION__ << ";;; Retrying premature received frame " <<
1169 premature_received_frames_ << " => " <<
1170 (premature_received_frames_ - 1);
1171 --premature_received_frames_;
1172 OnWebVRFrameAvailable();
1173 }
1174
1071 base::TimeTicks now = base::TimeTicks::Now(); 1175 base::TimeTicks now = base::TimeTicks::Now();
1072 base::TimeTicks target; 1176 base::TimeTicks target;
1073 1177
1074 // Don't send VSyncs until we have a timebase/interval. 1178 // Don't send VSyncs until we have a timebase/interval.
1075 if (vsync_interval_.is_zero()) 1179 if (vsync_interval_.is_zero())
1076 return; 1180 return;
1077 target = now + vsync_interval_; 1181 target = now + vsync_interval_;
1078 int64_t intervals = (target - vsync_timebase_) / vsync_interval_; 1182 int64_t intervals = (target - vsync_timebase_) / vsync_interval_;
1079 target = vsync_timebase_ + intervals * vsync_interval_; 1183 target = vsync_timebase_ + intervals * vsync_interval_;
1080 task_runner_->PostDelayedTask(FROM_HERE, vsync_task_.callback(), 1184 task_runner_->PostDelayedTask(FROM_HERE, vsync_task_.callback(),
1081 target - now); 1185 target - now);
1082 1186
1083 base::TimeDelta time = intervals * vsync_interval_; 1187 base::TimeDelta time = intervals * vsync_interval_;
1188 // Send a small rate of vsyncs even while backlogged to avoid
1189 // locking up when the rAF loop doesn't submit a frame.
1190 static int skip_counter = 0;
1084 if (!callback_.is_null()) { 1191 if (!callback_.is_null()) {
1085 SendVSync(time, base::ResetAndReturn(&callback_)); 1192 if (requested_frames_ < 1 || (++skip_counter % 30) == 0) {
1193 VLOG(1) << __FUNCTION__ << ";;; vsync B, interval=" << vsync_interval_;
1194 SendVSync(time, base::ResetAndReturn(&callback_));
1195 } else {
1196 VLOG(1) << __FUNCTION__ << ";;; Skip vsync B, already have frame requested ";
1197 return;
1198 }
1086 } else { 1199 } else {
1087 pending_vsync_ = true; 1200 pending_vsync_ = true;
1088 pending_time_ = time; 1201 pending_time_ = time;
1089 } 1202 }
1090 DrawFrame(); 1203 if (!web_vr_mode_) {
1204 DrawFrame(-1);
1205 }
1091 } 1206 }
1092 1207
1093 void VrShellGl::OnRequest(device::mojom::VRVSyncProviderRequest request) { 1208 void VrShellGl::OnRequest(device::mojom::VRVSyncProviderRequest request) {
1094 binding_.Close(); 1209 binding_.Close();
1095 binding_.Bind(std::move(request)); 1210 binding_.Bind(std::move(request));
1096 } 1211 }
1097 1212
1098 void VrShellGl::GetVSync(const GetVSyncCallback& callback) { 1213 void VrShellGl::GetVSync(const GetVSyncCallback& callback) {
1099 if (!pending_vsync_) { 1214 if (!pending_vsync_) {
1100 if (!callback_.is_null()) { 1215 if (!callback_.is_null()) {
1101 mojo::ReportBadMessage( 1216 mojo::ReportBadMessage(
1102 "Requested VSync before waiting for response to previous request."); 1217 "Requested VSync before waiting for response to previous request.");
1103 binding_.Close(); 1218 binding_.Close();
1104 return; 1219 return;
1105 } 1220 }
1106 callback_ = callback; 1221 callback_ = callback;
1107 return; 1222 return;
1108 } 1223 }
1109 pending_vsync_ = false; 1224 pending_vsync_ = false;
1225 VLOG(1) << __FUNCTION__ << ";;; vsync A, pending time=" << pending_time_;
1110 SendVSync(pending_time_, callback); 1226 SendVSync(pending_time_, callback);
1111 } 1227 }
1112 1228
1113 void VrShellGl::UpdateVSyncInterval(int64_t timebase_nanos, 1229 void VrShellGl::UpdateVSyncInterval(int64_t timebase_nanos,
1114 double interval_seconds) { 1230 double interval_seconds) {
1115 vsync_timebase_ = base::TimeTicks(); 1231 vsync_timebase_ = base::TimeTicks();
1116 vsync_timebase_ += base::TimeDelta::FromMicroseconds(timebase_nanos / 1000); 1232 vsync_timebase_ += base::TimeDelta::FromMicroseconds(timebase_nanos / 1000);
1117 vsync_interval_ = base::TimeDelta::FromSecondsD(interval_seconds); 1233 vsync_interval_ = base::TimeDelta::FromSecondsD(interval_seconds);
1118 vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this))); 1234 vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this)));
1235 VLOG(1) << __FUNCTION__ << ";;; vsync_interval=" << vsync_interval_;
1119 OnVSync(); 1236 OnVSync();
1120 } 1237 }
1121 1238
1122 void VrShellGl::ForceExitVr() { 1239 void VrShellGl::ForceExitVr() {
1123 main_thread_task_runner_->PostTask( 1240 main_thread_task_runner_->PostTask(
1124 FROM_HERE, base::Bind(&VrShell::ForceExitVr, weak_vr_shell_)); 1241 FROM_HERE, base::Bind(&VrShell::ForceExitVr, weak_vr_shell_));
1125 } 1242 }
1126 1243
1127 void VrShellGl::UpdateScene(std::unique_ptr<base::ListValue> commands) { 1244 void VrShellGl::UpdateScene(std::unique_ptr<base::ListValue> commands) {
1128 scene_->HandleCommands(std::move(commands), TimeInMicroseconds()); 1245 scene_->HandleCommands(std::move(commands), TimeInMicroseconds());
1129 } 1246 }
1130 1247
1131 void VrShellGl::SendVSync(base::TimeDelta time, 1248 void VrShellGl::SendVSync(base::TimeDelta time,
1132 const GetVSyncCallback& callback) { 1249 const GetVSyncCallback& callback) {
1133 TRACE_EVENT0("input", "VrShellGl::SendVSync"); 1250 TRACE_EVENT0("input", "VrShellGl::SendVSync");
1134 1251
1252 VLOG(1) << __FUNCTION__ << ";;; requested_frames " << requested_frames_ <<
1253 " => " << (requested_frames_ + 1);
1254 ++requested_frames_;
1255
1135 uint8_t frame_index = frame_index_++; 1256 uint8_t frame_index = frame_index_++;
1257 VLOG(1) << __FUNCTION__ << ";;; vsync for frame=" << (int)frame_index;
1136 1258
1137 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); 1259 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow();
1138 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; 1260 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos;
1139 1261
1140 gvr::Mat4f head_mat = 1262 gvr::Mat4f head_mat =
1141 gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time); 1263 gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time);
1142 head_mat = gvr_api_->ApplyNeckModel(head_mat, 1.0f); 1264 head_mat = gvr_api_->ApplyNeckModel(head_mat, 1.0f);
1143 1265
1144 webvr_head_pose_[frame_index % kPoseRingBufferSize] = head_mat; 1266 webvr_head_pose_[frame_index % kPoseRingBufferSize] = head_mat;
1145 1267
(...skipping 12 matching lines...) Expand all
1158 const base::Callback<void(device::mojom::VRDisplayInfoPtr)>& callback, 1280 const base::Callback<void(device::mojom::VRDisplayInfoPtr)>& callback,
1159 uint32_t device_id) { 1281 uint32_t device_id) {
1160 device::mojom::VRDisplayInfoPtr info = VrShell::CreateVRDisplayInfo( 1282 device::mojom::VRDisplayInfoPtr info = VrShell::CreateVRDisplayInfo(
1161 gvr_api_.get(), content_tex_physical_size_, device_id); 1283 gvr_api_.get(), content_tex_physical_size_, device_id);
1162 main_thread_task_runner_->PostTask( 1284 main_thread_task_runner_->PostTask(
1163 FROM_HERE, 1285 FROM_HERE,
1164 base::Bind(&RunVRDisplayInfoCallback, callback, base::Passed(&info))); 1286 base::Bind(&RunVRDisplayInfoCallback, callback, base::Passed(&info)));
1165 } 1287 }
1166 1288
1167 } // namespace vr_shell 1289 } // namespace vr_shell
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698