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

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: Further cleanups 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"
11 #include "base/callback_helpers.h" 11 #include "base/callback_helpers.h"
12 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
13 #include "base/metrics/histogram_macros.h" 13 #include "base/metrics/histogram_macros.h"
14 #include "base/threading/thread_task_runner_handle.h" 14 #include "base/threading/thread_task_runner_handle.h"
15 #include "chrome/browser/android/vr_shell/ui_elements.h" 15 #include "chrome/browser/android/vr_shell/ui_elements.h"
16 #include "chrome/browser/android/vr_shell/ui_scene.h" 16 #include "chrome/browser/android/vr_shell/ui_scene.h"
17 #include "chrome/browser/android/vr_shell/vr_controller.h" 17 #include "chrome/browser/android/vr_shell/vr_controller.h"
18 #include "chrome/browser/android/vr_shell/vr_gl_util.h" 18 #include "chrome/browser/android/vr_shell/vr_gl_util.h"
19 #include "chrome/browser/android/vr_shell/vr_math.h" 19 #include "chrome/browser/android/vr_shell/vr_math.h"
20 #include "chrome/browser/android/vr_shell/vr_shell.h" 20 #include "chrome/browser/android/vr_shell/vr_shell.h"
21 #include "chrome/browser/android/vr_shell/vr_shell_command_buffer_gl.h"
21 #include "chrome/browser/android/vr_shell/vr_shell_delegate.h" 22 #include "chrome/browser/android/vr_shell/vr_shell_delegate.h"
22 #include "chrome/browser/android/vr_shell/vr_shell_renderer.h" 23 #include "chrome/browser/android/vr_shell/vr_shell_renderer.h"
23 #include "device/vr/android/gvr/gvr_device.h" 24 #include "device/vr/android/gvr/gvr_device.h"
24 #include "third_party/WebKit/public/platform/WebInputEvent.h" 25 #include "third_party/WebKit/public/platform/WebInputEvent.h"
25 #include "third_party/WebKit/public/platform/WebMouseEvent.h" 26 #include "third_party/WebKit/public/platform/WebMouseEvent.h"
26 #include "ui/gl/android/scoped_java_surface.h" 27 #include "ui/gl/android/scoped_java_surface.h"
27 #include "ui/gl/android/surface_texture.h" 28 #include "ui/gl/android/surface_texture.h"
28 #include "ui/gl/gl_bindings.h" 29 #include "ui/gl/gl_bindings.h"
29 #include "ui/gl/gl_context.h" 30 #include "ui/gl/gl_context.h"
30 #include "ui/gl/gl_surface.h" 31 #include "ui/gl/gl_surface.h"
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 77
77 // The GVR viewport list has two entries (left eye and right eye) for each 78 // The GVR viewport list has two entries (left eye and right eye) for each
78 // GVR buffer. 79 // GVR buffer.
79 static constexpr int kViewportListPrimaryOffset = 0; 80 static constexpr int kViewportListPrimaryOffset = 0;
80 static constexpr int kViewportListHeadlockedOffset = 2; 81 static constexpr int kViewportListHeadlockedOffset = 2;
81 82
82 // Buffer size large enough to handle the current backlog of poses which is 83 // Buffer size large enough to handle the current backlog of poses which is
83 // 2-3 frames. 84 // 2-3 frames.
84 static constexpr unsigned kPoseRingBufferSize = 8; 85 static constexpr unsigned kPoseRingBufferSize = 8;
85 86
86 // 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.
88 static constexpr std::array<uint8_t, 2> kWebVrPosePixelMagicNumbers{{42, 142}};
89
90 float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) { 87 float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) {
91 float xdiff = (vec1.x - vec2.x); 88 float xdiff = (vec1.x - vec2.x);
92 float ydiff = (vec1.y - vec2.y); 89 float ydiff = (vec1.y - vec2.y);
93 float zdiff = (vec1.z - vec2.z); 90 float zdiff = (vec1.z - vec2.z);
94 float scale = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff; 91 float scale = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff;
95 return std::sqrt(scale); 92 return std::sqrt(scale);
96 } 93 }
97 94
98 // Generate a quaternion representing the rotation from the negative Z axis 95 // Generate a quaternion representing the rotation from the negative Z axis
99 // (0, 0, -1) to a specified vector. This is an optimized version of a more 96 // (0, 0, -1) to a specified vector. This is an optimized version of a more
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 LOG(ERROR) << "gl::init::CreateGLContext failed"; 225 LOG(ERROR) << "gl::init::CreateGLContext failed";
229 ForceExitVr(); 226 ForceExitVr();
230 return; 227 return;
231 } 228 }
232 if (!context_->MakeCurrent(surface_.get())) { 229 if (!context_->MakeCurrent(surface_.get())) {
233 LOG(ERROR) << "gl::GLContext::MakeCurrent() failed"; 230 LOG(ERROR) << "gl::GLContext::MakeCurrent() failed";
234 ForceExitVr(); 231 ForceExitVr();
235 return; 232 return;
236 } 233 }
237 234
238 unsigned int textures[2]; 235 unsigned int textures[3];
239 glGenTextures(2, textures); 236 glGenTextures(3, textures);
240 ui_texture_id_ = textures[0]; 237 ui_texture_id_ = textures[0];
241 content_texture_id_ = textures[1]; 238 content_texture_id_ = textures[1];
239 webvr_texture_id_ = textures[2];
242 ui_surface_texture_ = gl::SurfaceTexture::Create(ui_texture_id_); 240 ui_surface_texture_ = gl::SurfaceTexture::Create(ui_texture_id_);
243 content_surface_texture_ = gl::SurfaceTexture::Create(content_texture_id_); 241 content_surface_texture_ = gl::SurfaceTexture::Create(content_texture_id_);
242 webvr_surface_texture_ = gl::SurfaceTexture::Create(webvr_texture_id_);
244 CreateUiSurface(); 243 CreateUiSurface();
245 CreateContentSurface(); 244 CreateContentSurface();
245 CreateWebVRSurface();
246 ui_surface_texture_->SetFrameAvailableCallback(base::Bind( 246 ui_surface_texture_->SetFrameAvailableCallback(base::Bind(
247 &VrShellGl::OnUIFrameAvailable, weak_ptr_factory_.GetWeakPtr())); 247 &VrShellGl::OnUIFrameAvailable, weak_ptr_factory_.GetWeakPtr()));
248 content_surface_texture_->SetFrameAvailableCallback(base::Bind( 248 content_surface_texture_->SetFrameAvailableCallback(base::Bind(
249 &VrShellGl::OnContentFrameAvailable, weak_ptr_factory_.GetWeakPtr())); 249 &VrShellGl::OnContentFrameAvailable, weak_ptr_factory_.GetWeakPtr()));
250 webvr_surface_texture_->SetFrameAvailableCallback(base::Bind(
251 &VrShellGl::OnWebVRFrameAvailable, weak_ptr_factory_.GetWeakPtr()));
252 ui_surface_texture_->SetDefaultBufferSize(ui_tex_physical_size_.width,
253 ui_tex_physical_size_.height);
250 content_surface_texture_->SetDefaultBufferSize( 254 content_surface_texture_->SetDefaultBufferSize(
251 content_tex_physical_size_.width, content_tex_physical_size_.height); 255 content_tex_physical_size_.width, content_tex_physical_size_.height);
252 ui_surface_texture_->SetDefaultBufferSize(ui_tex_physical_size_.width,
253 ui_tex_physical_size_.height);
254 InitializeRenderer(); 256 InitializeRenderer();
255 257
256 vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this))); 258 vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this)));
257 OnVSync(); 259 OnVSync();
258 260
259 ready_to_draw_ = true; 261 ready_to_draw_ = true;
260 } 262 }
261 263
264
262 void VrShellGl::CreateContentSurface() { 265 void VrShellGl::CreateContentSurface() {
263 content_surface_ = 266 content_surface_ =
264 base::MakeUnique<gl::ScopedJavaSurface>(content_surface_texture_.get()); 267 base::MakeUnique<gl::ScopedJavaSurface>(content_surface_texture_.get());
265 main_thread_task_runner_->PostTask( 268 main_thread_task_runner_->PostTask(
266 FROM_HERE, base::Bind(&VrShell::ContentSurfaceChanged, weak_vr_shell_, 269 FROM_HERE, base::Bind(&VrShell::ContentSurfaceChanged, weak_vr_shell_,
267 content_surface_->j_surface().obj())); 270 content_surface_->j_surface().obj()));
268 } 271 }
269 272
270 void VrShellGl::CreateUiSurface() { 273 void VrShellGl::CreateUiSurface() {
271 ui_surface_ = 274 ui_surface_ =
272 base::MakeUnique<gl::ScopedJavaSurface>(ui_surface_texture_.get()); 275 base::MakeUnique<gl::ScopedJavaSurface>(ui_surface_texture_.get());
273 main_thread_task_runner_->PostTask( 276 main_thread_task_runner_->PostTask(
274 FROM_HERE, base::Bind(&VrShell::UiSurfaceChanged, weak_vr_shell_, 277 FROM_HERE, base::Bind(&VrShell::UiSurfaceChanged, weak_vr_shell_,
275 ui_surface_->j_surface().obj())); 278 ui_surface_->j_surface().obj()));
276 } 279 }
277 280
281 void VrShellGl::CreateWebVRSurface() {
282 VLOG(1) << __FUNCTION__ << ";;; content_tex_physical_size=" <<
283 content_tex_physical_size_.width << "x" <<
284 content_tex_physical_size_.height;
285 VLOG(1) << __FUNCTION__ << ";;; render_size_primary=" <<
286 render_size_primary_.width << "x" << render_size_primary_.height;
287 // FIXME: get correct sizes. Currently getting 0x0 from the
288 // likely candidates. For now, hardcode Pixel XL resolution.
289 // This will work on other devices too, though it's not the most
290 // efficient.
291 webvr_surface_texture_->SetDefaultBufferSize(2560, 1440);
292
293 command_buffer_gl_ = base::MakeUnique<VrShellCommandBufferGl>();
294 command_buffer_gl_->CreateContext(webvr_surface_texture_);
295 }
296
297 void VrShellGl::SubmitWebVRFrame(int frame_index, const gpu::Mailbox& mailbox) {
298 TRACE_EVENT0("gpu", "VrShellGl::SubmitWebVRFrame");
299 bool drawn = command_buffer_gl_->CopyFrameToSurface(
300 frame_index, mailbox, !pending_frames_.empty());
301 // If we get here, we're committed to drawing and swapBuffers.
302 // Continue after errors.
303 if (drawn) {
304 VLOG(1) << __FUNCTION__ << ";;; add frame=" << frame_index <<
305 " to pending_frames, size=" << pending_frames_.size();
306 main_thread_task_runner_->PostTask(
307 FROM_HERE, base::Bind(&VrShell::OnSubmitWebVRFrameTransferred,
308 weak_vr_shell_, frame_index));
309 pending_frames_.emplace(frame_index);
310 } else {
311 VLOG(1) << __FUNCTION__ << ";;; NOT DRAWN, FIXME!";
312 }
313 }
314
278 void VrShellGl::OnUIFrameAvailable() { 315 void VrShellGl::OnUIFrameAvailable() {
316 VLOG(1) << __FUNCTION__ << ";;; UI UpdateTexImage start";
279 ui_surface_texture_->UpdateTexImage(); 317 ui_surface_texture_->UpdateTexImage();
318 VLOG(1) << __FUNCTION__ << ";;; UI UpdateTexImage end";
280 } 319 }
281 320
282 void VrShellGl::OnContentFrameAvailable() { 321 void VrShellGl::OnContentFrameAvailable() {
322 VLOG(1) << __FUNCTION__ << ";;; Content UpdateTexImage start";
283 content_surface_texture_->UpdateTexImage(); 323 content_surface_texture_->UpdateTexImage();
284 received_frame_ = true; 324 received_frame_ = true;
325 VLOG(1) << __FUNCTION__ << ";;; Content UpdateTexImage end";
285 } 326 }
286 327
287 bool VrShellGl::GetPixelEncodedFrameIndex(uint16_t* frame_index) { 328 void VrShellGl::OnWebVRFrameAvailable() {
288 TRACE_EVENT0("gpu", "VrShellGl::GetPixelEncodedFrameIndex"); 329 TRACE_EVENT0("gpu", "VrShellGl::OnWebVRFrameAvailable");
289 if (!received_frame_) { 330 VLOG(1) << __FUNCTION__ << ";;; pending count=" << pending_frames_.size();
290 if (last_frame_index_ == (uint16_t)-1) 331 // A "while" loop here is a bad idea. It's legal to call
291 return false; 332 // UpdateTexImage repeatedly even if no frames are available, but
292 *frame_index = last_frame_index_; 333 // that does *not* wait for a new frame, it just reuses the most
293 return true; 334 // recent one. That would mess up the count.
335 if (pending_frames_.empty()) {
336 VLOG(1) << __FUNCTION__ << ";;; no pending frames? Please retry! " <<
337 "premature_received_frames " << premature_received_frames_ << " => " <<
338 (premature_received_frames_ + 1);
339 ++premature_received_frames_;
340 return;
294 } 341 }
295 received_frame_ = false;
296 342
297 // Read the pose index encoded in a bottom left pixel as color values. 343 VLOG(1) << __FUNCTION__ << ";;; WebVR UpdateTexImage start";
298 // See also third_party/WebKit/Source/modules/vr/VRDisplay.cpp which 344 webvr_surface_texture_->UpdateTexImage();
299 // encodes the pose index, and device/vr/android/gvr/gvr_device.cc 345 int frame_index = pending_frames_.front();
300 // which tracks poses. Returns the low byte (0..255) if valid, or -1 346 pending_frames_.pop();
301 // if not valid due to bad magic number. 347 VLOG(1) << __FUNCTION__ << ";;; WebVR UpdateTexImage end, got frame=" <<
302 uint8_t pixels[4]; 348 frame_index;
303 // Assume we're reading from the framebuffer we just wrote to. 349 main_thread_task_runner_->PostTask(
304 // That's true currently, we may need to use glReadBuffer(GL_BACK) 350 FROM_HERE, base::Bind(&VrShell::OnSubmitWebVRFrameRendered,
305 // or equivalent if the rendering setup changes in the future. 351 weak_vr_shell_, frame_index));
306 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 352 DrawFrame(frame_index);
307
308 // Check for the magic number written by VRDevice.cpp on submit.
309 // This helps avoid glitches from garbage data in the render
310 // buffer that can appear during initialization or resizing. These
311 // often appear as flashes of all-black or all-white pixels.
312 if (pixels[1] == kWebVrPosePixelMagicNumbers[0] &&
313 pixels[2] == kWebVrPosePixelMagicNumbers[1]) {
314 // Pose is good.
315 *frame_index = pixels[0];
316 last_frame_index_ = pixels[0];
317 return true;
318 }
319 VLOG(1) << "WebVR: reject decoded pose index " << static_cast<int>(pixels[0])
320 << ", bad magic number " << static_cast<int>(pixels[1]) << ", "
321 << static_cast<int>(pixels[2]);
322 return false;
323 } 353 }
324 354
325 void VrShellGl::GvrInit(gvr_context* gvr_api) { 355 void VrShellGl::GvrInit(gvr_context* gvr_api) {
326 gvr_api_ = gvr::GvrApi::WrapNonOwned(gvr_api); 356 gvr_api_ = gvr::GvrApi::WrapNonOwned(gvr_api);
327 controller_.reset(new VrController(gvr_api)); 357 controller_.reset(new VrController(gvr_api));
328 358
329 ViewerType viewerType; 359 ViewerType viewerType;
330 switch (gvr_api_->GetViewerType()) { 360 switch (gvr_api_->GetViewerType()) {
331 case gvr::ViewerType::GVR_VIEWER_TYPE_DAYDREAM: 361 case gvr::ViewerType::GVR_VIEWER_TYPE_DAYDREAM:
332 viewerType = ViewerType::DAYDREAM; 362 viewerType = ViewerType::DAYDREAM;
333 break; 363 break;
334 case gvr::ViewerType::GVR_VIEWER_TYPE_CARDBOARD: 364 case gvr::ViewerType::GVR_VIEWER_TYPE_CARDBOARD:
335 viewerType = ViewerType::CARDBOARD; 365 viewerType = ViewerType::CARDBOARD;
336 break; 366 break;
337 default: 367 default:
338 NOTREACHED(); 368 NOTREACHED();
339 viewerType = ViewerType::UNKNOWN_TYPE; 369 viewerType = ViewerType::UNKNOWN_TYPE;
340 break; 370 break;
341 } 371 }
342 UMA_HISTOGRAM_ENUMERATION("VRViewerType", static_cast<int>(viewerType), 372 UMA_HISTOGRAM_ENUMERATION("VRViewerType", static_cast<int>(viewerType),
343 static_cast<int>(ViewerType::VIEWER_TYPE_MAX)); 373 static_cast<int>(ViewerType::VIEWER_TYPE_MAX));
344 } 374 }
345 375
346 void VrShellGl::InitializeRenderer() { 376 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(); 377 gvr_api_->InitializeGl();
354 webvr_head_pose_.assign(kPoseRingBufferSize, 378 webvr_head_pose_.assign(kPoseRingBufferSize,
355 gvr_api_->GetHeadSpaceFromStartSpaceRotation( 379 gvr_api_->GetHeadSpaceFromStartSpaceRotation(
356 gvr::GvrApi::GetTimePointNow())); 380 gvr::GvrApi::GetTimePointNow()));
357 381
358 std::vector<gvr::BufferSpec> specs; 382 std::vector<gvr::BufferSpec> specs;
359 // For kFramePrimaryBuffer (primary VrShell and WebVR content) 383 // For kFramePrimaryBuffer (primary VrShell and WebVR content)
360 specs.push_back(gvr_api_->CreateBufferSpec()); 384 specs.push_back(gvr_api_->CreateBufferSpec());
361 render_size_primary_ = specs[kFramePrimaryBuffer].GetSize(); 385 render_size_primary_ = specs[kFramePrimaryBuffer].GetSize();
362 386
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 std::unique_ptr<blink::WebInputEvent> event) { 647 std::unique_ptr<blink::WebInputEvent> event) {
624 DCHECK(input_target != InputTarget::NONE); 648 DCHECK(input_target != InputTarget::NONE);
625 auto&& target = input_target == InputTarget::CONTENT 649 auto&& target = input_target == InputTarget::CONTENT
626 ? &VrShell::ProcessContentGesture 650 ? &VrShell::ProcessContentGesture
627 : &VrShell::ProcessUIGesture; 651 : &VrShell::ProcessUIGesture;
628 main_thread_task_runner_->PostTask( 652 main_thread_task_runner_->PostTask(
629 FROM_HERE, 653 FROM_HERE,
630 base::Bind(target, weak_vr_shell_, base::Passed(std::move(event)))); 654 base::Bind(target, weak_vr_shell_, base::Passed(std::move(event))));
631 } 655 }
632 656
633 void VrShellGl::DrawFrame() { 657 void VrShellGl::DrawFrame(int frame_index) {
634 TRACE_EVENT0("gpu", "VrShellGl::DrawFrame"); 658 TRACE_EVENT0("gpu", "VrShellGl::DrawFrame");
635 659
636 // Reset the viewport list to just the pair of viewports for the 660 // Reset the viewport list to just the pair of viewports for the
637 // primary buffer each frame. Head-locked viewports get added by 661 // primary buffer each frame. Head-locked viewports get added by
638 // DrawVrShell if needed. 662 // DrawVrShell if needed.
639 buffer_viewport_list_->SetToRecommendedBufferViewports(); 663 buffer_viewport_list_->SetToRecommendedBufferViewports();
640 664
665 TRACE_EVENT_BEGIN0("gpu", "VrShellGl::AcquireFrame");
641 gvr::Frame frame = swap_chain_->AcquireFrame(); 666 gvr::Frame frame = swap_chain_->AcquireFrame();
667 TRACE_EVENT_END0("gpu", "VrShellGl::AcquireFrame");
642 if (!frame.is_valid()) { 668 if (!frame.is_valid()) {
643 return; 669 return;
644 } 670 }
645 frame.BindBuffer(kFramePrimaryBuffer); 671 frame.BindBuffer(kFramePrimaryBuffer);
646 if (web_vr_mode_) { 672 if (web_vr_mode_) {
647 DrawWebVr(); 673 DrawWebVr();
648 } 674 }
649 675
650 uint16_t frame_index;
651 gvr::Mat4f head_pose; 676 gvr::Mat4f head_pose;
652 677
653 // When using async reprojection, we need to know which pose was used in 678 // 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 679 // the WebVR app for drawing this frame. Due to unknown amounts of
655 // buffering in the compositor and SurfaceTexture, we read the pose number 680 // 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 681 // 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 682 // distortion rendering since that doesn't need a pose, and reading back
658 // pixels is an expensive operation. TODO(klausw,crbug.com/655722): stop 683 // pixels is an expensive operation. TODO(klausw,crbug.com/655722): stop
659 // doing this once we have working no-compositor rendering for WebVR. 684 // doing this once we have working no-compositor rendering for WebVR.
660 if (web_vr_mode_ && gvr_api_->GetAsyncReprojectionEnabled() && 685 if (web_vr_mode_ && gvr_api_->GetAsyncReprojectionEnabled()) {
661 GetPixelEncodedFrameIndex(&frame_index)) {
662 static_assert(!((kPoseRingBufferSize - 1) & kPoseRingBufferSize), 686 static_assert(!((kPoseRingBufferSize - 1) & kPoseRingBufferSize),
663 "kPoseRingBufferSize must be a power of 2"); 687 "kPoseRingBufferSize must be a power of 2");
664 head_pose = webvr_head_pose_[frame_index % kPoseRingBufferSize]; 688 head_pose = webvr_head_pose_[frame_index % kPoseRingBufferSize];
665 // Process all pending_bounds_ changes targeted for before this frame, being 689 // Process all pending_bounds_ changes targeted for before this frame, being
666 // careful of wrapping frame indices. 690 // careful of wrapping frame indices.
667 static constexpr unsigned max = 691 static constexpr unsigned max =
668 std::numeric_limits<decltype(frame_index_)>::max(); 692 std::numeric_limits<decltype(frame_index_)>::max();
669 static_assert(max > kPoseRingBufferSize * 2, 693 static_assert(max > kPoseRingBufferSize * 2,
670 "To detect wrapping, kPoseRingBufferSize must be smaller " 694 "To detect wrapping, kPoseRingBufferSize must be smaller "
671 "than half of frame_index_ range."); 695 "than half of frame_index_ range.");
672 while (!pending_bounds_.empty()) { 696 while (!pending_bounds_.empty()) {
673 uint16_t index = pending_bounds_.front().first; 697 uint16_t index = pending_bounds_.front().first;
698 VLOG(1) << __FUNCTION__ << ";;; new bounds, index=" << index;
674 // If index is less than the frame_index it's possible we've wrapped, so 699 // 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. 700 // we extend the range and 'un-wrap' to account for this.
676 if (index < frame_index) 701 if (index < frame_index)
677 index += max; 702 index += max;
678 // If the pending bounds change is for an upcoming frame within our buffer 703 // If the pending bounds change is for an upcoming frame within our buffer
679 // size, wait to apply it. Otherwise, apply it immediately. This 704 // 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 705 // guarantees that even if we miss many frames, the queue can't fill up
681 // with stale bounds. 706 // with stale bounds.
682 if (index > frame_index && index <= frame_index + kPoseRingBufferSize) 707 if (index > frame_index && index <= frame_index + kPoseRingBufferSize)
683 break; 708 break;
(...skipping 20 matching lines...) Expand all
704 // object_from_reference_matrix, we're not updating position_external. 729 // object_from_reference_matrix, we're not updating position_external.
705 // TODO: Not sure what object_from_reference_matrix is. The new api removed 730 // TODO: Not sure what object_from_reference_matrix is. The new api removed
706 // it. For now, removing it seems working fine. 731 // it. For now, removing it seems working fine.
707 gvr_api_->ApplyNeckModel(head_pose, 1.0f); 732 gvr_api_->ApplyNeckModel(head_pose, 1.0f);
708 } 733 }
709 734
710 // Update the render position of all UI elements (including desktop). 735 // Update the render position of all UI elements (including desktop).
711 const float screen_tilt = kDesktopScreenTiltDefault * M_PI / 180.0f; 736 const float screen_tilt = kDesktopScreenTiltDefault * M_PI / 180.0f;
712 scene_->UpdateTransforms(screen_tilt, TimeInMicroseconds()); 737 scene_->UpdateTransforms(screen_tilt, TimeInMicroseconds());
713 738
714 UpdateController(GetForwardVector(head_pose)); 739 {
740 TRACE_EVENT0("gpu", "VrShellGl::UpdateController");
741 UpdateController(GetForwardVector(head_pose));
742 }
715 743
716 DrawVrShell(head_pose, frame); 744 // Drawing VrShell causes GL error 0x501 GL_INVALID_VALUE while in
745 // WebVR mode. FIXME.
746 if (!web_vr_mode_) DrawVrShell(head_pose, frame);
717 747
718 frame.Unbind(); 748 {
719 frame.Submit(*buffer_viewport_list_, head_pose); 749 TRACE_EVENT0("gpu", "VrShellGl::Submit");
750 frame.Unbind();
751 frame.Submit(*buffer_viewport_list_, head_pose);
752 }
720 753
721 // No need to swap buffers for surfaceless rendering. 754 // No need to swap buffers for surfaceless rendering.
722 if (!surfaceless_rendering_) { 755 if (!surfaceless_rendering_) {
723 // TODO(mthiesse): Support asynchronous SwapBuffers. 756 // TODO(mthiesse): Support asynchronous SwapBuffers.
757 TRACE_EVENT0("gpu", "VrShellGl::SwapBuffers");
724 surface_->SwapBuffers(); 758 surface_->SwapBuffers();
725 } 759 }
726 } 760 }
727 761
728 void VrShellGl::DrawVrShell(const gvr::Mat4f& head_pose, gvr::Frame& frame) { 762 void VrShellGl::DrawVrShell(const gvr::Mat4f& head_pose, gvr::Frame& frame) {
729 TRACE_EVENT0("gpu", "VrShellGl::DrawVrShell"); 763 TRACE_EVENT0("gpu", "VrShellGl::DrawVrShell");
730 std::vector<const ContentRectangle*> head_locked_elements; 764 std::vector<const ContentRectangle*> head_locked_elements;
731 std::vector<const ContentRectangle*> world_elements; 765 std::vector<const ContentRectangle*> world_elements;
732 for (const auto& rect : scene_->GetUiElements()) { 766 for (const auto& rect : scene_->GetUiElements()) {
733 if (!rect->IsVisible()) 767 if (!rect->IsVisible())
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
992 // Don't need face culling, depth testing, blending, etc. Turn it all off. 1026 // Don't need face culling, depth testing, blending, etc. Turn it all off.
993 glDisable(GL_CULL_FACE); 1027 glDisable(GL_CULL_FACE);
994 glDepthMask(GL_FALSE); 1028 glDepthMask(GL_FALSE);
995 glDisable(GL_DEPTH_TEST); 1029 glDisable(GL_DEPTH_TEST);
996 glDisable(GL_SCISSOR_TEST); 1030 glDisable(GL_SCISSOR_TEST);
997 glDisable(GL_BLEND); 1031 glDisable(GL_BLEND);
998 glDisable(GL_POLYGON_OFFSET_FILL); 1032 glDisable(GL_POLYGON_OFFSET_FILL);
999 1033
1000 glViewport(0, 0, render_size_primary_.width, render_size_primary_.height); 1034 glViewport(0, 0, render_size_primary_.width, render_size_primary_.height);
1001 vr_shell_renderer_->GetWebVrRenderer()->Draw(webvr_texture_id_); 1035 vr_shell_renderer_->GetWebVrRenderer()->Draw(webvr_texture_id_);
1036 VLOG(1) << __FUNCTION__ << ";;; WebVrRenderer done";
1002 } 1037 }
1003 1038
1004 void VrShellGl::OnTriggerEvent() { 1039 void VrShellGl::OnTriggerEvent() {
1005 // Set a flag to handle this on the render thread at the next frame. 1040 // Set a flag to handle this on the render thread at the next frame.
1006 touch_pending_ = true; 1041 touch_pending_ = true;
1007 } 1042 }
1008 1043
1009 void VrShellGl::OnPause() { 1044 void VrShellGl::OnPause() {
1010 vsync_task_.Cancel(); 1045 vsync_task_.Cancel();
1011 controller_->OnPause(); 1046 controller_->OnPause();
(...skipping 10 matching lines...) Expand all
1022 } 1057 }
1023 } 1058 }
1024 1059
1025 void VrShellGl::SetWebVrMode(bool enabled) { 1060 void VrShellGl::SetWebVrMode(bool enabled) {
1026 web_vr_mode_ = enabled; 1061 web_vr_mode_ = enabled;
1027 } 1062 }
1028 1063
1029 void VrShellGl::UpdateWebVRTextureBounds(int16_t frame_index, 1064 void VrShellGl::UpdateWebVRTextureBounds(int16_t frame_index,
1030 const gvr::Rectf& left_bounds, 1065 const gvr::Rectf& left_bounds,
1031 const gvr::Rectf& right_bounds) { 1066 const gvr::Rectf& right_bounds) {
1067 VLOG(1) << __FUNCTION__ << ";;; frame_index=" << frame_index <<
1068 " left=" << left_bounds.left << "," << left_bounds.bottom <<
1069 "," << left_bounds.right << "," << left_bounds.top <<
1070 " right=" << right_bounds.left << "," << right_bounds.bottom <<
1071 "," << right_bounds.right << "," << right_bounds.top;
1032 if (frame_index < 0) { 1072 if (frame_index < 0) {
1033 webvr_left_viewport_->SetSourceUv(left_bounds); 1073 webvr_left_viewport_->SetSourceUv(left_bounds);
1034 webvr_right_viewport_->SetSourceUv(right_bounds); 1074 webvr_right_viewport_->SetSourceUv(right_bounds);
1035 } else { 1075 } else {
1036 pending_bounds_.emplace( 1076 pending_bounds_.emplace(
1037 std::make_pair(frame_index, std::make_pair(left_bounds, right_bounds))); 1077 std::make_pair(frame_index, std::make_pair(left_bounds, right_bounds)));
1038 } 1078 }
1039 } 1079 }
1040 1080
1041 void VrShellGl::ContentBoundsChanged(int width, int height) { 1081 void VrShellGl::ContentBoundsChanged(int width, int height) {
(...skipping 19 matching lines...) Expand all
1061 ui_surface_texture_->SetDefaultBufferSize(width, height); 1101 ui_surface_texture_->SetDefaultBufferSize(width, height);
1062 ui_tex_physical_size_.width = width; 1102 ui_tex_physical_size_.width = width;
1063 ui_tex_physical_size_.height = height; 1103 ui_tex_physical_size_.height = height;
1064 } 1104 }
1065 1105
1066 base::WeakPtr<VrShellGl> VrShellGl::GetWeakPtr() { 1106 base::WeakPtr<VrShellGl> VrShellGl::GetWeakPtr() {
1067 return weak_ptr_factory_.GetWeakPtr(); 1107 return weak_ptr_factory_.GetWeakPtr();
1068 } 1108 }
1069 1109
1070 void VrShellGl::OnVSync() { 1110 void VrShellGl::OnVSync() {
1111 while (premature_received_frames_ > 0) {
1112 VLOG(1) << __FUNCTION__ << ";;; Retrying premature received frame " <<
1113 premature_received_frames_ << " => " <<
1114 (premature_received_frames_ - 1);
1115 --premature_received_frames_;
1116 OnWebVRFrameAvailable();
1117 }
1118
1071 base::TimeTicks now = base::TimeTicks::Now(); 1119 base::TimeTicks now = base::TimeTicks::Now();
1072 base::TimeTicks target; 1120 base::TimeTicks target;
1073 1121
1074 // Don't send VSyncs until we have a timebase/interval. 1122 // Don't send VSyncs until we have a timebase/interval.
1075 if (vsync_interval_.is_zero()) 1123 if (vsync_interval_.is_zero())
1076 return; 1124 return;
1077 target = now + vsync_interval_; 1125 target = now + vsync_interval_;
1078 int64_t intervals = (target - vsync_timebase_) / vsync_interval_; 1126 int64_t intervals = (target - vsync_timebase_) / vsync_interval_;
1079 target = vsync_timebase_ + intervals * vsync_interval_; 1127 target = vsync_timebase_ + intervals * vsync_interval_;
1080 task_runner_->PostDelayedTask(FROM_HERE, vsync_task_.callback(), 1128 task_runner_->PostDelayedTask(FROM_HERE, vsync_task_.callback(),
1081 target - now); 1129 target - now);
1082 1130
1083 base::TimeDelta time = intervals * vsync_interval_; 1131 base::TimeDelta time = intervals * vsync_interval_;
1084 if (!callback_.is_null()) { 1132 if (!callback_.is_null()) {
1133 VLOG(1) << __FUNCTION__ << ";;; vsync B, interval=" << vsync_interval_;
1085 SendVSync(time, base::ResetAndReturn(&callback_)); 1134 SendVSync(time, base::ResetAndReturn(&callback_));
1086 } else { 1135 } else {
1087 pending_vsync_ = true; 1136 pending_vsync_ = true;
1088 pending_time_ = time; 1137 pending_time_ = time;
1089 } 1138 }
1090 DrawFrame(); 1139 if (!web_vr_mode_) {
1140 DrawFrame(-1);
1141 }
1091 } 1142 }
1092 1143
1093 void VrShellGl::OnRequest(device::mojom::VRVSyncProviderRequest request) { 1144 void VrShellGl::OnRequest(device::mojom::VRVSyncProviderRequest request) {
1094 binding_.Close(); 1145 binding_.Close();
1095 binding_.Bind(std::move(request)); 1146 binding_.Bind(std::move(request));
1096 } 1147 }
1097 1148
1098 void VrShellGl::GetVSync(const GetVSyncCallback& callback) { 1149 void VrShellGl::GetVSync(const GetVSyncCallback& callback) {
1099 if (!pending_vsync_) { 1150 if (!pending_vsync_) {
1100 if (!callback_.is_null()) { 1151 if (!callback_.is_null()) {
1101 mojo::ReportBadMessage( 1152 mojo::ReportBadMessage(
1102 "Requested VSync before waiting for response to previous request."); 1153 "Requested VSync before waiting for response to previous request.");
1103 binding_.Close(); 1154 binding_.Close();
1104 return; 1155 return;
1105 } 1156 }
1106 callback_ = callback; 1157 callback_ = callback;
1107 return; 1158 return;
1108 } 1159 }
1109 pending_vsync_ = false; 1160 pending_vsync_ = false;
1161 VLOG(1) << __FUNCTION__ << ";;; vsync A, pending time=" << pending_time_;
1110 SendVSync(pending_time_, callback); 1162 SendVSync(pending_time_, callback);
1163
1164 // FIXME: A glFinish here triggers flickering?
1165 // if (web_vr_mode_) glFinish();
1111 } 1166 }
1112 1167
1113 void VrShellGl::UpdateVSyncInterval(int64_t timebase_nanos, 1168 void VrShellGl::UpdateVSyncInterval(int64_t timebase_nanos,
1114 double interval_seconds) { 1169 double interval_seconds) {
1115 vsync_timebase_ = base::TimeTicks(); 1170 vsync_timebase_ = base::TimeTicks();
1116 vsync_timebase_ += base::TimeDelta::FromMicroseconds(timebase_nanos / 1000); 1171 vsync_timebase_ += base::TimeDelta::FromMicroseconds(timebase_nanos / 1000);
1117 vsync_interval_ = base::TimeDelta::FromSecondsD(interval_seconds); 1172 vsync_interval_ = base::TimeDelta::FromSecondsD(interval_seconds);
1118 vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this))); 1173 vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this)));
1174 VLOG(1) << __FUNCTION__ << ";;; vsync_interval=" << vsync_interval_;
1119 OnVSync(); 1175 OnVSync();
1120 } 1176 }
1121 1177
1122 void VrShellGl::ForceExitVr() { 1178 void VrShellGl::ForceExitVr() {
1123 main_thread_task_runner_->PostTask( 1179 main_thread_task_runner_->PostTask(
1124 FROM_HERE, base::Bind(&VrShell::ForceExitVr, weak_vr_shell_)); 1180 FROM_HERE, base::Bind(&VrShell::ForceExitVr, weak_vr_shell_));
1125 } 1181 }
1126 1182
1127 void VrShellGl::UpdateScene(std::unique_ptr<base::ListValue> commands) { 1183 void VrShellGl::UpdateScene(std::unique_ptr<base::ListValue> commands) {
1128 scene_->HandleCommands(std::move(commands), TimeInMicroseconds()); 1184 scene_->HandleCommands(std::move(commands), TimeInMicroseconds());
1129 } 1185 }
1130 1186
1131 void VrShellGl::SendVSync(base::TimeDelta time, 1187 void VrShellGl::SendVSync(base::TimeDelta time,
1132 const GetVSyncCallback& callback) { 1188 const GetVSyncCallback& callback) {
1133 TRACE_EVENT0("input", "VrShellGl::SendVSync"); 1189 TRACE_EVENT0("input", "VrShellGl::SendVSync");
1134 1190
1135 uint8_t frame_index = frame_index_++; 1191 uint8_t frame_index = frame_index_++;
1192 VLOG(1) << __FUNCTION__ << ";;; vsync for frame=" <<
1193 static_cast<int>(frame_index);
1136 1194
1137 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); 1195 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow();
1138 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; 1196 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos;
1139 1197
1140 gvr::Mat4f head_mat = 1198 gvr::Mat4f head_mat =
1141 gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time); 1199 gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time);
1142 head_mat = gvr_api_->ApplyNeckModel(head_mat, 1.0f); 1200 head_mat = gvr_api_->ApplyNeckModel(head_mat, 1.0f);
1143 1201
1144 webvr_head_pose_[frame_index % kPoseRingBufferSize] = head_mat; 1202 webvr_head_pose_[frame_index % kPoseRingBufferSize] = head_mat;
1145 1203
(...skipping 12 matching lines...) Expand all
1158 const base::Callback<void(device::mojom::VRDisplayInfoPtr)>& callback, 1216 const base::Callback<void(device::mojom::VRDisplayInfoPtr)>& callback,
1159 uint32_t device_id) { 1217 uint32_t device_id) {
1160 device::mojom::VRDisplayInfoPtr info = VrShell::CreateVRDisplayInfo( 1218 device::mojom::VRDisplayInfoPtr info = VrShell::CreateVRDisplayInfo(
1161 gvr_api_.get(), content_tex_physical_size_, device_id); 1219 gvr_api_.get(), content_tex_physical_size_, device_id);
1162 main_thread_task_runner_->PostTask( 1220 main_thread_task_runner_->PostTask(
1163 FROM_HERE, 1221 FROM_HERE,
1164 base::Bind(&RunVRDisplayInfoCallback, callback, base::Passed(&info))); 1222 base::Bind(&RunVRDisplayInfoCallback, callback, base::Passed(&info)));
1165 } 1223 }
1166 1224
1167 } // namespace vr_shell 1225 } // namespace vr_shell
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698