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

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: Fix SubmitFrameClient corner case, fix unittest compilation. 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/mailbox_to_surface_bridge.h"
15 #include "chrome/browser/android/vr_shell/ui_elements.h" 16 #include "chrome/browser/android/vr_shell/ui_elements.h"
16 #include "chrome/browser/android/vr_shell/ui_scene.h" 17 #include "chrome/browser/android/vr_shell/ui_scene.h"
17 #include "chrome/browser/android/vr_shell/vr_controller.h" 18 #include "chrome/browser/android/vr_shell/vr_controller.h"
18 #include "chrome/browser/android/vr_shell/vr_gl_util.h" 19 #include "chrome/browser/android/vr_shell/vr_gl_util.h"
19 #include "chrome/browser/android/vr_shell/vr_math.h" 20 #include "chrome/browser/android/vr_shell/vr_math.h"
20 #include "chrome/browser/android/vr_shell/vr_shell.h" 21 #include "chrome/browser/android/vr_shell/vr_shell.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"
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 74
74 // The GVR viewport list has two entries (left eye and right eye) for each 75 // The GVR viewport list has two entries (left eye and right eye) for each
75 // GVR buffer. 76 // GVR buffer.
76 static constexpr int kViewportListPrimaryOffset = 0; 77 static constexpr int kViewportListPrimaryOffset = 0;
77 static constexpr int kViewportListHeadlockedOffset = 2; 78 static constexpr int kViewportListHeadlockedOffset = 2;
78 79
79 // Buffer size large enough to handle the current backlog of poses which is 80 // Buffer size large enough to handle the current backlog of poses which is
80 // 2-3 frames. 81 // 2-3 frames.
81 static constexpr unsigned kPoseRingBufferSize = 8; 82 static constexpr unsigned kPoseRingBufferSize = 8;
82 83
83 // Magic numbers used to mark valid pose index values encoded in frame 84 // Default downscale factor for computing the recommended WebVR
84 // data. Must match the magic numbers used in blink's VRDisplay.cpp. 85 // renderWidth/Height from the 1:1 pixel mapped size. Using a rather
85 static constexpr std::array<uint8_t, 2> kWebVrPosePixelMagicNumbers{{42, 142}}; 86 // aggressive downscale due to the high overhead of copying pixels
87 // twice before handing off to GVR. For comparison, the polyfill
88 // uses approximately 0.55 on a Pixel XL.
89 static constexpr float kWebVrRecommendedResolutionScale = 0.5;
86 90
87 float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) { 91 float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) {
88 float xdiff = (vec1.x - vec2.x); 92 float xdiff = (vec1.x - vec2.x);
89 float ydiff = (vec1.y - vec2.y); 93 float ydiff = (vec1.y - vec2.y);
90 float zdiff = (vec1.z - vec2.z); 94 float zdiff = (vec1.z - vec2.z);
91 float scale = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff; 95 float scale = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff;
92 return std::sqrt(scale); 96 return std::sqrt(scale);
93 } 97 }
94 98
95 // Generate a quaternion representing the rotation from the negative Z axis 99 // Generate a quaternion representing the rotation from the negative Z axis
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 binding_(this), 169 binding_(this),
166 weak_vr_shell_(weak_vr_shell), 170 weak_vr_shell_(weak_vr_shell),
167 delegate_provider_(delegate_provider), 171 delegate_provider_(delegate_provider),
168 main_thread_task_runner_(std::move(main_thread_task_runner)), 172 main_thread_task_runner_(std::move(main_thread_task_runner)),
169 weak_ptr_factory_(this) { 173 weak_ptr_factory_(this) {
170 GvrInit(gvr_api); 174 GvrInit(gvr_api);
171 } 175 }
172 176
173 VrShellGl::~VrShellGl() { 177 VrShellGl::~VrShellGl() {
174 vsync_task_.Cancel(); 178 vsync_task_.Cancel();
179 binding_.Close();
dcheng 2017/03/08 07:23:39 Please add a comment why it's necessary to explici
klausw 2017/03/08 08:11:09 Does the comment below the next line make it clear
mthiesse 2017/03/08 13:44:48 I wrote this - my concern was that it might be pos
klausw 2017/03/08 16:58:51 Added as a comment. Just to clarify, mthiesse@ con
dcheng 2017/03/08 23:08:05 OK, thanks. In the case of non-sync calls (which i
175 if (!callback_.is_null()) { 180 if (!callback_.is_null()) {
176 // When this VSync provider is going away we have to respond to pending 181 // When this VSync provider is going away we have to respond to pending
177 // callbacks, so instead of providing a VSync, tell the requester to try 182 // callbacks, so instead of providing a VSync, tell the requester to try
178 // again. A VSyncProvider is guaranteed to exist, so the request in response 183 // again. A VSyncProvider is guaranteed to exist, so the request in response
179 // to this message will go through some other VSyncProvider. 184 // to this message will go through some other VSyncProvider.
180 base::ResetAndReturn(&callback_) 185 base::ResetAndReturn(&callback_)
181 .Run(nullptr, base::TimeDelta(), -1, 186 .Run(nullptr, base::TimeDelta(), -1,
182 device::mojom::VRVSyncProvider::Status::RETRY); 187 device::mojom::VRVSyncProvider::Status::CLOSING);
183 }
184 if (binding_.is_bound()) {
185 main_thread_task_runner_->PostTask(
186 FROM_HERE,
187 base::Bind(&VrShellDelegate::OnVRVsyncProviderRequest,
188 delegate_provider_, base::Passed(binding_.Unbind())));
189 } 188 }
190 } 189 }
191 190
192 void VrShellGl::Initialize() { 191 void VrShellGl::Initialize() {
193 scene_.reset(new UiScene); 192 scene_.reset(new UiScene);
194 193
195 if (surfaceless_rendering_) { 194 if (surfaceless_rendering_) {
196 // If we're rendering surfaceless, we'll never get a java surface to render 195 // If we're rendering surfaceless, we'll never get a java surface to render
197 // into, so we can initialize GL right away. 196 // into, so we can initialize GL right away.
198 InitializeGl(nullptr); 197 InitializeGl(nullptr);
(...skipping 26 matching lines...) Expand all
225 LOG(ERROR) << "gl::init::CreateGLContext failed"; 224 LOG(ERROR) << "gl::init::CreateGLContext failed";
226 ForceExitVr(); 225 ForceExitVr();
227 return; 226 return;
228 } 227 }
229 if (!context_->MakeCurrent(surface_.get())) { 228 if (!context_->MakeCurrent(surface_.get())) {
230 LOG(ERROR) << "gl::GLContext::MakeCurrent() failed"; 229 LOG(ERROR) << "gl::GLContext::MakeCurrent() failed";
231 ForceExitVr(); 230 ForceExitVr();
232 return; 231 return;
233 } 232 }
234 233
235 unsigned int textures[2]; 234 unsigned int textures[3];
236 glGenTextures(2, textures); 235 glGenTextures(3, textures);
237 ui_texture_id_ = textures[0]; 236 ui_texture_id_ = textures[0];
238 content_texture_id_ = textures[1]; 237 content_texture_id_ = textures[1];
238 webvr_texture_id_ = textures[2];
239 ui_surface_texture_ = gl::SurfaceTexture::Create(ui_texture_id_); 239 ui_surface_texture_ = gl::SurfaceTexture::Create(ui_texture_id_);
240 content_surface_texture_ = gl::SurfaceTexture::Create(content_texture_id_); 240 content_surface_texture_ = gl::SurfaceTexture::Create(content_texture_id_);
241 webvr_surface_texture_ = gl::SurfaceTexture::Create(webvr_texture_id_);
241 CreateUiSurface(); 242 CreateUiSurface();
242 CreateContentSurface(); 243 CreateContentSurface();
243 ui_surface_texture_->SetFrameAvailableCallback(base::Bind( 244 ui_surface_texture_->SetFrameAvailableCallback(base::Bind(
244 &VrShellGl::OnUIFrameAvailable, weak_ptr_factory_.GetWeakPtr())); 245 &VrShellGl::OnUIFrameAvailable, weak_ptr_factory_.GetWeakPtr()));
245 content_surface_texture_->SetFrameAvailableCallback(base::Bind( 246 content_surface_texture_->SetFrameAvailableCallback(base::Bind(
246 &VrShellGl::OnContentFrameAvailable, weak_ptr_factory_.GetWeakPtr())); 247 &VrShellGl::OnContentFrameAvailable, weak_ptr_factory_.GetWeakPtr()));
248 webvr_surface_texture_->SetFrameAvailableCallback(base::Bind(
249 &VrShellGl::OnWebVRFrameAvailable, weak_ptr_factory_.GetWeakPtr()));
250 ui_surface_texture_->SetDefaultBufferSize(ui_tex_physical_size_.width,
251 ui_tex_physical_size_.height);
247 content_surface_texture_->SetDefaultBufferSize( 252 content_surface_texture_->SetDefaultBufferSize(
248 content_tex_physical_size_.width, content_tex_physical_size_.height); 253 content_tex_physical_size_.width, content_tex_physical_size_.height);
249 ui_surface_texture_->SetDefaultBufferSize(ui_tex_physical_size_.width,
250 ui_tex_physical_size_.height);
251 InitializeRenderer(); 254 InitializeRenderer();
252 255
256 // Pick a reasonable default size for the WebVR transfer surface
257 // based on a downscaled 1:1 render resolution. This size will also
258 // be reported to the client via CreateVRDisplayInfo as the
259 // client-recommended renderWidth/renderHeight and for the GVR
260 // framebuffer. If the client chooses a different size or resizes it
261 // while presenting, we'll resize the transfer surface and GVR
262 // framebuffer to match.
263 auto render_target_size = gvr_api_->GetMaximumEffectiveRenderTargetSize();
dcheng 2017/03/08 07:23:39 Can this be explicitly typed?
klausw 2017/03/08 08:11:09 Done.
264 gvr::Sizei webvr_size = {static_cast<int>(render_target_size.width *
265 kWebVrRecommendedResolutionScale),
266 static_cast<int>(render_target_size.height *
267 kWebVrRecommendedResolutionScale)};
268
269 // TODO(klausw,crbug.com/699350): should we round the recommended
270 // size to a multiple of 2^N pixels to be friendlier to the GPU? The
271 // exact size doesn't matter.
272
273 CreateOrResizeWebVRSurface(webvr_size);
274
253 vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this))); 275 vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this)));
254 OnVSync(); 276 OnVSync();
255 277
256 ready_to_draw_ = true; 278 ready_to_draw_ = true;
257 } 279 }
258 280
259 void VrShellGl::CreateContentSurface() { 281 void VrShellGl::CreateContentSurface() {
260 content_surface_ = 282 content_surface_ =
261 base::MakeUnique<gl::ScopedJavaSurface>(content_surface_texture_.get()); 283 base::MakeUnique<gl::ScopedJavaSurface>(content_surface_texture_.get());
262 main_thread_task_runner_->PostTask( 284 main_thread_task_runner_->PostTask(
263 FROM_HERE, base::Bind(&VrShell::ContentSurfaceChanged, weak_vr_shell_, 285 FROM_HERE, base::Bind(&VrShell::ContentSurfaceChanged, weak_vr_shell_,
264 content_surface_->j_surface().obj())); 286 content_surface_->j_surface().obj()));
265 } 287 }
266 288
267 void VrShellGl::CreateUiSurface() { 289 void VrShellGl::CreateUiSurface() {
268 ui_surface_ = 290 ui_surface_ =
269 base::MakeUnique<gl::ScopedJavaSurface>(ui_surface_texture_.get()); 291 base::MakeUnique<gl::ScopedJavaSurface>(ui_surface_texture_.get());
270 main_thread_task_runner_->PostTask( 292 main_thread_task_runner_->PostTask(
271 FROM_HERE, base::Bind(&VrShell::UiSurfaceChanged, weak_vr_shell_, 293 FROM_HERE, base::Bind(&VrShell::UiSurfaceChanged, weak_vr_shell_,
272 ui_surface_->j_surface().obj())); 294 ui_surface_->j_surface().obj()));
273 } 295 }
274 296
297 void VrShellGl::CreateOrResizeWebVRSurface(const gvr::Sizei& size) {
298 if (!webvr_surface_texture_) {
299 DLOG(ERROR) << "No WebVR surface texture available";
300 return;
301 }
302
303 // ContentPhysicalBoundsChanged is getting called twice with
304 // identical sizes? Avoid thrashing the existing context.
305 if (size == webvr_surface_size_) {
306 return;
307 }
308
309 if (!size.width || !size.height) {
310 // Invalid size, defer until a new size arrives on a future bounds update.
311 return;
312 }
313
314 webvr_surface_texture_->SetDefaultBufferSize(size.width, size.height);
315 webvr_surface_size_ = size;
316
317 if (mailbox_bridge_) {
318 mailbox_bridge_->ResizeSurface(size.width, size.height);
319 } else {
320 mailbox_bridge_ = base::MakeUnique<MailboxToSurfaceBridge>();
321 mailbox_bridge_->CreateSurface(webvr_surface_texture_);
322 }
323 }
324
325 void VrShellGl::SubmitWebVRFrame(int16_t frame_index,
326 const gpu::MailboxHolder& mailbox) {
327 TRACE_EVENT0("gpu", "VrShellGl::SubmitWebVRFrame");
328
329 // Swapping twice on a Surface without calling updateTexImage in
330 // between can lose frames, so don't draw+swap if we already have
331 // a pending frame we haven't consumed yet.
332 bool swapped = false;
333 if (pending_frames_.empty()) {
334 swapped = mailbox_bridge_->CopyMailboxToSurfaceAndSwap(mailbox);
335 if (swapped) {
336 // Tell OnWebVRFrameAvailable to expect a new frame to arrive on
337 // the SurfaceTexture, and save the associated frame index.
338 pending_frames_.emplace(frame_index);
339 }
340 }
341 // Always notify the client that we're done with the mailbox even
342 // if we haven't drawn it, so that it's eligible for destruction.
343 submit_client_->OnSubmitFrameTransferred();
344 if (!swapped) {
345 // We dropped without drawing, report this as completed rendering
346 // now to unblock the client. We're not going to receive it in
347 // OnWebVRFrameAvailable where we'd normally report that.
348 submit_client_->OnSubmitFrameRendered();
349 }
350
351 TRACE_EVENT0("gpu", "VrShellGl::glFinish");
352 // This is a load-bearing glFinish, please don't remove it without
353 // before/after timing comparisons. Goal is to clear the GPU queue
354 // of the native GL context to avoid stalls later in GVR frame
355 // acquire/submit.
356 glFinish();
357 }
358
359 void VrShellGl::SetSubmitClient(
360 device::mojom::VRSubmitFrameClientPtrInfo submit_client_info) {
361 submit_client_.Bind(std::move(submit_client_info));
362 }
363
275 void VrShellGl::OnUIFrameAvailable() { 364 void VrShellGl::OnUIFrameAvailable() {
276 ui_surface_texture_->UpdateTexImage(); 365 ui_surface_texture_->UpdateTexImage();
277 } 366 }
278 367
279 void VrShellGl::OnContentFrameAvailable() { 368 void VrShellGl::OnContentFrameAvailable() {
280 content_surface_texture_->UpdateTexImage(); 369 content_surface_texture_->UpdateTexImage();
281 received_frame_ = true; 370 received_frame_ = true;
282 } 371 }
283 372
284 bool VrShellGl::GetPixelEncodedFrameIndex(uint16_t* frame_index) { 373 void VrShellGl::OnWebVRFrameAvailable() {
285 TRACE_EVENT0("gpu", "VrShellGl::GetPixelEncodedFrameIndex"); 374 // A "while" loop here is a bad idea. It's legal to call
286 if (!received_frame_) { 375 // UpdateTexImage repeatedly even if no frames are available, but
287 if (last_frame_index_ == (uint16_t)-1) 376 // that does *not* wait for a new frame, it just reuses the most
288 return false; 377 // recent one. That would mess up the count.
289 *frame_index = last_frame_index_; 378 if (pending_frames_.empty()) {
290 return true; 379 // We're expecting a frame, but it's not here yet. Retry in OnVsync.
380 ++premature_received_frames_;
381 return;
291 } 382 }
292 received_frame_ = false;
293 383
294 // Read the pose index encoded in a bottom left pixel as color values. 384 webvr_surface_texture_->UpdateTexImage();
295 // See also third_party/WebKit/Source/modules/vr/VRDisplay.cpp which 385 int frame_index = pending_frames_.front();
296 // encodes the pose index, and device/vr/android/gvr/gvr_device.cc 386 TRACE_EVENT1("gpu", "VrShellGl::OnWebVRFrameAvailable", "frame", frame_index);
297 // which tracks poses. Returns the low byte (0..255) if valid, or -1 387 pending_frames_.pop();
298 // if not valid due to bad magic number.
299 uint8_t pixels[4];
300 // Assume we're reading from the framebuffer we just wrote to.
301 // That's true currently, we may need to use glReadBuffer(GL_BACK)
302 // or equivalent if the rendering setup changes in the future.
303 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
304 388
305 // Check for the magic number written by VRDevice.cpp on submit. 389 // It is legal for the WebVR client to submit a new frame now, since
306 // This helps avoid glitches from garbage data in the render 390 // we've consumed the image. TODO(klausw): would timing be better if
307 // buffer that can appear during initialization or resizing. These 391 // we move the "rendered" notification after draw, or suppress
308 // often appear as flashes of all-black or all-white pixels. 392 // the next vsync until that's done?
309 if (pixels[1] == kWebVrPosePixelMagicNumbers[0] && 393
310 pixels[2] == kWebVrPosePixelMagicNumbers[1]) { 394 submit_client_->OnSubmitFrameRendered();
311 // Pose is good. 395
312 *frame_index = pixels[0]; 396 DrawFrame(frame_index);
313 last_frame_index_ = pixels[0];
314 return true;
315 }
316 VLOG(1) << "WebVR: reject decoded pose index " << static_cast<int>(pixels[0])
317 << ", bad magic number " << static_cast<int>(pixels[1]) << ", "
318 << static_cast<int>(pixels[2]);
319 return false;
320 } 397 }
321 398
322 void VrShellGl::GvrInit(gvr_context* gvr_api) { 399 void VrShellGl::GvrInit(gvr_context* gvr_api) {
323 gvr_api_ = gvr::GvrApi::WrapNonOwned(gvr_api); 400 gvr_api_ = gvr::GvrApi::WrapNonOwned(gvr_api);
324 controller_.reset(new VrController(gvr_api)); 401 controller_.reset(new VrController(gvr_api));
325 402
326 ViewerType viewerType; 403 ViewerType viewerType;
327 switch (gvr_api_->GetViewerType()) { 404 switch (gvr_api_->GetViewerType()) {
328 case gvr::ViewerType::GVR_VIEWER_TYPE_DAYDREAM: 405 case gvr::ViewerType::GVR_VIEWER_TYPE_DAYDREAM:
329 viewerType = ViewerType::DAYDREAM; 406 viewerType = ViewerType::DAYDREAM;
330 break; 407 break;
331 case gvr::ViewerType::GVR_VIEWER_TYPE_CARDBOARD: 408 case gvr::ViewerType::GVR_VIEWER_TYPE_CARDBOARD:
332 viewerType = ViewerType::CARDBOARD; 409 viewerType = ViewerType::CARDBOARD;
333 break; 410 break;
334 default: 411 default:
335 NOTREACHED(); 412 NOTREACHED();
336 viewerType = ViewerType::UNKNOWN_TYPE; 413 viewerType = ViewerType::UNKNOWN_TYPE;
337 break; 414 break;
338 } 415 }
339 UMA_HISTOGRAM_ENUMERATION("VRViewerType", static_cast<int>(viewerType), 416 UMA_HISTOGRAM_ENUMERATION("VRViewerType", static_cast<int>(viewerType),
340 static_cast<int>(ViewerType::VIEWER_TYPE_MAX)); 417 static_cast<int>(ViewerType::VIEWER_TYPE_MAX));
341 } 418 }
342 419
343 void VrShellGl::InitializeRenderer() { 420 void VrShellGl::InitializeRenderer() {
344 // While WebVR is going through the compositor path, it shares
345 // the same texture ID. This will change once it gets its own
346 // surface, but store it separately to avoid future confusion.
347 // TODO(klausw,crbug.com/655722): remove this.
348 webvr_texture_id_ = content_texture_id_;
349
350 gvr_api_->InitializeGl(); 421 gvr_api_->InitializeGl();
351 webvr_head_pose_.assign(kPoseRingBufferSize, 422 webvr_head_pose_.assign(kPoseRingBufferSize,
352 gvr_api_->GetHeadSpaceFromStartSpaceRotation( 423 gvr_api_->GetHeadSpaceFromStartSpaceRotation(
353 gvr::GvrApi::GetTimePointNow())); 424 gvr::GvrApi::GetTimePointNow()));
354 425
355 std::vector<gvr::BufferSpec> specs; 426 std::vector<gvr::BufferSpec> specs;
356 // For kFramePrimaryBuffer (primary VrShell and WebVR content) 427 // For kFramePrimaryBuffer (primary VrShell and WebVR content)
357 specs.push_back(gvr_api_->CreateBufferSpec()); 428 specs.push_back(gvr_api_->CreateBufferSpec());
358 render_size_primary_ = specs[kFramePrimaryBuffer].GetSize(); 429 render_size_primary_ = specs[kFramePrimaryBuffer].GetSize();
430 render_size_vrshell_ = render_size_primary_;
359 431
360 // For kFrameHeadlockedBuffer (for WebVR insecure content warning). 432 // For kFrameHeadlockedBuffer (for WebVR insecure content warning).
361 // Set this up at fixed resolution, the (smaller) FOV gets set below. 433 // Set this up at fixed resolution, the (smaller) FOV gets set below.
362 specs.push_back(gvr_api_->CreateBufferSpec()); 434 specs.push_back(gvr_api_->CreateBufferSpec());
363 specs.back().SetSize(kHeadlockedBufferDimensions); 435 specs.back().SetSize(kHeadlockedBufferDimensions);
364 render_size_headlocked_ = specs[kFrameHeadlockedBuffer].GetSize(); 436 render_size_headlocked_ = specs[kFrameHeadlockedBuffer].GetSize();
365 437
366 swap_chain_.reset(new gvr::SwapChain(gvr_api_->CreateSwapChain(specs))); 438 swap_chain_.reset(new gvr::SwapChain(gvr_api_->CreateSwapChain(specs)));
367 439
368 vr_shell_renderer_.reset(new VrShellRenderer()); 440 vr_shell_renderer_.reset(new VrShellRenderer());
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
625 std::unique_ptr<blink::WebInputEvent> event) { 697 std::unique_ptr<blink::WebInputEvent> event) {
626 DCHECK(input_target != InputTarget::NONE); 698 DCHECK(input_target != InputTarget::NONE);
627 auto&& target = input_target == InputTarget::CONTENT 699 auto&& target = input_target == InputTarget::CONTENT
628 ? &VrShell::ProcessContentGesture 700 ? &VrShell::ProcessContentGesture
629 : &VrShell::ProcessUIGesture; 701 : &VrShell::ProcessUIGesture;
630 main_thread_task_runner_->PostTask( 702 main_thread_task_runner_->PostTask(
631 FROM_HERE, 703 FROM_HERE,
632 base::Bind(target, weak_vr_shell_, base::Passed(std::move(event)))); 704 base::Bind(target, weak_vr_shell_, base::Passed(std::move(event))));
633 } 705 }
634 706
635 void VrShellGl::DrawFrame() { 707 void VrShellGl::DrawFrame(int frame_index) {
dcheng 2017/03/08 07:23:39 int16_t to match the other frame_index type?
klausw 2017/03/08 08:11:09 Done.
636 TRACE_EVENT0("gpu", "VrShellGl::DrawFrame"); 708 TRACE_EVENT1("gpu", "VrShellGl::DrawFrame", "frame", frame_index);
637 709
638 // 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
639 // primary buffer each frame. Head-locked viewports get added by 711 // primary buffer each frame. Head-locked viewports get added by
640 // DrawVrShell if needed. 712 // DrawVrShell if needed.
641 buffer_viewport_list_->SetToRecommendedBufferViewports(); 713 buffer_viewport_list_->SetToRecommendedBufferViewports();
642 714
715 // If needed, resize the primary buffer for use with WebVR.
716 if (web_vr_mode_) {
717 if (render_size_primary_ != webvr_surface_size_) {
718 if (!webvr_surface_size_.width) {
719 return;
720 }
721 render_size_primary_ = webvr_surface_size_;
722 swap_chain_->ResizeBuffer(kFramePrimaryBuffer, render_size_primary_);
723 }
724 } else {
725 if (render_size_primary_ != render_size_vrshell_) {
726 render_size_primary_ = render_size_vrshell_;
727 swap_chain_->ResizeBuffer(kFramePrimaryBuffer, render_size_primary_);
728 }
729 }
730
731 TRACE_EVENT_BEGIN0("gpu", "VrShellGl::AcquireFrame");
643 gvr::Frame frame = swap_chain_->AcquireFrame(); 732 gvr::Frame frame = swap_chain_->AcquireFrame();
733 TRACE_EVENT_END0("gpu", "VrShellGl::AcquireFrame");
644 if (!frame.is_valid()) { 734 if (!frame.is_valid()) {
645 return; 735 return;
646 } 736 }
647 frame.BindBuffer(kFramePrimaryBuffer); 737 frame.BindBuffer(kFramePrimaryBuffer);
648 if (web_vr_mode_) { 738 if (web_vr_mode_) {
649 DrawWebVr(); 739 DrawWebVr();
650 } 740 }
651 741
652 uint16_t frame_index;
653 gvr::Mat4f head_pose; 742 gvr::Mat4f head_pose;
654 743
655 // When using async reprojection, we need to know which pose was used in 744 // When using async reprojection, we need to know which pose was used in
656 // the WebVR app for drawing this frame. Due to unknown amounts of 745 // the WebVR app for drawing this frame. Only needed if reprojection is
657 // buffering in the compositor and SurfaceTexture, we read the pose number 746 // in use.
658 // from a corner pixel. There's no point in doing this for legacy 747 if (web_vr_mode_ && gvr_api_->GetAsyncReprojectionEnabled()) {
659 // distortion rendering since that doesn't need a pose, and reading back
660 // pixels is an expensive operation. TODO(klausw,crbug.com/655722): stop
661 // doing this once we have working no-compositor rendering for WebVR.
662 if (web_vr_mode_ && gvr_api_->GetAsyncReprojectionEnabled() &&
663 GetPixelEncodedFrameIndex(&frame_index)) {
664 static_assert(!((kPoseRingBufferSize - 1) & kPoseRingBufferSize), 748 static_assert(!((kPoseRingBufferSize - 1) & kPoseRingBufferSize),
665 "kPoseRingBufferSize must be a power of 2"); 749 "kPoseRingBufferSize must be a power of 2");
666 head_pose = webvr_head_pose_[frame_index % kPoseRingBufferSize]; 750 head_pose = webvr_head_pose_[frame_index % kPoseRingBufferSize];
667 // Process all pending_bounds_ changes targeted for before this frame, being 751 // Process all pending_bounds_ changes targeted for before this frame, being
668 // careful of wrapping frame indices. 752 // careful of wrapping frame indices.
669 static constexpr unsigned max = 753 static constexpr unsigned max =
670 std::numeric_limits<decltype(frame_index_)>::max(); 754 std::numeric_limits<decltype(frame_index_)>::max();
671 static_assert(max > kPoseRingBufferSize * 2, 755 static_assert(max > kPoseRingBufferSize * 2,
672 "To detect wrapping, kPoseRingBufferSize must be smaller " 756 "To detect wrapping, kPoseRingBufferSize must be smaller "
673 "than half of frame_index_ range."); 757 "than half of frame_index_ range.");
674 while (!pending_bounds_.empty()) { 758 while (!pending_bounds_.empty()) {
675 uint16_t index = pending_bounds_.front().first; 759 uint16_t index = pending_bounds_.front().first;
676 // If index is less than the frame_index it's possible we've wrapped, so 760 // If index is less than the frame_index it's possible we've wrapped, so
677 // we extend the range and 'un-wrap' to account for this. 761 // we extend the range and 'un-wrap' to account for this.
678 if (index < frame_index) 762 if (index < frame_index)
679 index += max; 763 index += max;
680 // If the pending bounds change is for an upcoming frame within our buffer 764 // If the pending bounds change is for an upcoming frame within our buffer
681 // size, wait to apply it. Otherwise, apply it immediately. This 765 // size, wait to apply it. Otherwise, apply it immediately. This
682 // guarantees that even if we miss many frames, the queue can't fill up 766 // guarantees that even if we miss many frames, the queue can't fill up
683 // with stale bounds. 767 // with stale bounds.
684 if (index > frame_index && index <= frame_index + kPoseRingBufferSize) 768 if (index > frame_index && index <= frame_index + kPoseRingBufferSize)
685 break; 769 break;
686 770
687 const BoundsPair& bounds = pending_bounds_.front().second; 771 const WebVrBounds& bounds = pending_bounds_.front().second;
688 webvr_left_viewport_->SetSourceUv(bounds.first); 772 webvr_left_viewport_->SetSourceUv(bounds.left_bounds);
689 webvr_right_viewport_->SetSourceUv(bounds.second); 773 webvr_right_viewport_->SetSourceUv(bounds.right_bounds);
774 CreateOrResizeWebVRSurface(bounds.source_size);
690 pending_bounds_.pop(); 775 pending_bounds_.pop();
691 } 776 }
692 buffer_viewport_list_->SetBufferViewport(GVR_LEFT_EYE, 777 buffer_viewport_list_->SetBufferViewport(GVR_LEFT_EYE,
693 *webvr_left_viewport_); 778 *webvr_left_viewport_);
694 buffer_viewport_list_->SetBufferViewport(GVR_RIGHT_EYE, 779 buffer_viewport_list_->SetBufferViewport(GVR_RIGHT_EYE,
695 *webvr_right_viewport_); 780 *webvr_right_viewport_);
696 } else { 781 } else {
697 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); 782 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow();
698 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; 783 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos;
699 head_pose = gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time); 784 head_pose = gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time);
700 } 785 }
701 786
702 gvr::Vec3f position = GetTranslation(head_pose); 787 gvr::Vec3f position = GetTranslation(head_pose);
703 if (position.x == 0.0f && position.y == 0.0f && position.z == 0.0f) { 788 if (position.x == 0.0f && position.y == 0.0f && position.z == 0.0f) {
704 // This appears to be a 3DOF pose without a neck model. Add one. 789 // This appears to be a 3DOF pose without a neck model. Add one.
705 // The head pose has redundant data. Assume we're only using the 790 // The head pose has redundant data. Assume we're only using the
706 // object_from_reference_matrix, we're not updating position_external. 791 // object_from_reference_matrix, we're not updating position_external.
707 // TODO: Not sure what object_from_reference_matrix is. The new api removed 792 // TODO: Not sure what object_from_reference_matrix is. The new api removed
708 // it. For now, removing it seems working fine. 793 // it. For now, removing it seems working fine.
709 gvr_api_->ApplyNeckModel(head_pose, 1.0f); 794 gvr_api_->ApplyNeckModel(head_pose, 1.0f);
710 } 795 }
711 796
712 // Update the render position of all UI elements (including desktop). 797 // Update the render position of all UI elements (including desktop).
713 scene_->UpdateTransforms(TimeInMicroseconds()); 798 scene_->UpdateTransforms(TimeInMicroseconds());
714 799
715 UpdateController(GetForwardVector(head_pose)); 800 {
801 TRACE_EVENT0("gpu", "VrShellGl::UpdateController");
802 UpdateController(GetForwardVector(head_pose));
803 }
716 804
717 DrawVrShell(head_pose, frame); 805 // Finish drawing in the primary buffer, and draw the headlocked buffer
806 // if needed. This must be the last drawing call, this method will
807 // return with no frame being bound.
808 DrawVrShellAndUnbind(head_pose, frame);
718 809
719 frame.Unbind(); 810 {
720 frame.Submit(*buffer_viewport_list_, head_pose); 811 TRACE_EVENT0("gpu", "VrShellGl::Submit");
812 frame.Submit(*buffer_viewport_list_, head_pose);
813 }
721 814
722 // No need to swap buffers for surfaceless rendering. 815 // No need to swap buffers for surfaceless rendering.
723 if (!surfaceless_rendering_) { 816 if (!surfaceless_rendering_) {
724 // TODO(mthiesse): Support asynchronous SwapBuffers. 817 // TODO(mthiesse): Support asynchronous SwapBuffers.
818 TRACE_EVENT0("gpu", "VrShellGl::SwapBuffers");
725 surface_->SwapBuffers(); 819 surface_->SwapBuffers();
726 } 820 }
727 } 821 }
728 822
729 void VrShellGl::DrawVrShell(const gvr::Mat4f& head_pose, gvr::Frame& frame) { 823 void VrShellGl::DrawVrShellAndUnbind(const gvr::Mat4f& head_pose,
824 gvr::Frame& frame) {
730 TRACE_EVENT0("gpu", "VrShellGl::DrawVrShell"); 825 TRACE_EVENT0("gpu", "VrShellGl::DrawVrShell");
731 std::vector<const ContentRectangle*> head_locked_elements; 826 std::vector<const ContentRectangle*> head_locked_elements;
732 std::vector<const ContentRectangle*> world_elements; 827 std::vector<const ContentRectangle*> world_elements;
733 for (const auto& rect : scene_->GetUiElements()) { 828 for (const auto& rect : scene_->GetUiElements()) {
734 if (!rect->IsVisible()) 829 if (!rect->IsVisible())
735 continue; 830 continue;
736 if (rect->lock_to_fov) { 831 if (rect->lock_to_fov) {
737 head_locked_elements.push_back(rect.get()); 832 head_locked_elements.push_back(rect.get());
738 } else { 833 } else {
739 world_elements.push_back(rect.get()); 834 world_elements.push_back(rect.get());
(...skipping 16 matching lines...) Expand all
756 851
757 const Colorf& backgroundColor = scene_->GetBackgroundColor(); 852 const Colorf& backgroundColor = scene_->GetBackgroundColor();
758 glClearColor(backgroundColor.r, backgroundColor.g, backgroundColor.b, 853 glClearColor(backgroundColor.r, backgroundColor.g, backgroundColor.b,
759 backgroundColor.a); 854 backgroundColor.a);
760 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 855 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
761 } 856 }
762 if (!world_elements.empty()) { 857 if (!world_elements.empty()) {
763 DrawUiView(&head_pose, world_elements, render_size_primary_, 858 DrawUiView(&head_pose, world_elements, render_size_primary_,
764 kViewportListPrimaryOffset); 859 kViewportListPrimaryOffset);
765 } 860 }
861 frame.Unbind(); // Done with the primary buffer.
766 862
767 if (!head_locked_elements.empty()) { 863 if (!head_locked_elements.empty()) {
768 // Add head-locked viewports. The list gets reset to just 864 // Add head-locked viewports. The list gets reset to just
769 // the recommended viewports (for the primary buffer) each frame. 865 // the recommended viewports (for the primary buffer) each frame.
770 buffer_viewport_list_->SetBufferViewport( 866 buffer_viewport_list_->SetBufferViewport(
771 kViewportListHeadlockedOffset + GVR_LEFT_EYE, 867 kViewportListHeadlockedOffset + GVR_LEFT_EYE,
772 *headlocked_left_viewport_); 868 *headlocked_left_viewport_);
773 buffer_viewport_list_->SetBufferViewport( 869 buffer_viewport_list_->SetBufferViewport(
774 kViewportListHeadlockedOffset + GVR_RIGHT_EYE, 870 kViewportListHeadlockedOffset + GVR_RIGHT_EYE,
775 *headlocked_right_viewport_); 871 *headlocked_right_viewport_);
776 872
777 // Bind the headlocked framebuffer. 873 // Bind the headlocked framebuffer.
778 // TODO(mthiesse): We don't unbind this? Maybe some cleanup is in order
779 // here.
780 frame.BindBuffer(kFrameHeadlockedBuffer); 874 frame.BindBuffer(kFrameHeadlockedBuffer);
781 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 875 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
782 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 876 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
783 DrawUiView(nullptr, head_locked_elements, render_size_headlocked_, 877 DrawUiView(nullptr, head_locked_elements, render_size_headlocked_,
784 kViewportListHeadlockedOffset); 878 kViewportListHeadlockedOffset);
879 frame.Unbind(); // Done with the headlocked buffer.
785 } 880 }
786 } 881 }
787 882
788 gvr::Sizei VrShellGl::GetWebVRCompositorSurfaceSize() {
789 // This is a stopgap while we're using the WebVR compositor rendering path.
790 // TODO(klausw,crbug.com/655722): Remove this method and member once we're
791 // using a separate WebVR render surface.
792 return content_tex_physical_size_;
793 }
794
795 void VrShellGl::DrawUiView(const gvr::Mat4f* head_pose, 883 void VrShellGl::DrawUiView(const gvr::Mat4f* head_pose,
796 const std::vector<const ContentRectangle*>& elements, 884 const std::vector<const ContentRectangle*>& elements,
797 const gvr::Sizei& render_size, 885 const gvr::Sizei& render_size,
798 int viewport_offset) { 886 int viewport_offset) {
799 TRACE_EVENT0("gpu", "VrShellGl::DrawUiView"); 887 TRACE_EVENT0("gpu", "VrShellGl::DrawUiView");
800 888
801 gvr::Mat4f view_matrix; 889 gvr::Mat4f view_matrix;
802 if (head_pose) { 890 if (head_pose) {
803 view_matrix = *head_pose; 891 view_matrix = *head_pose;
804 } else { 892 } else {
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
990 void VrShellGl::DrawWebVr() { 1078 void VrShellGl::DrawWebVr() {
991 TRACE_EVENT0("gpu", "VrShellGl::DrawWebVr"); 1079 TRACE_EVENT0("gpu", "VrShellGl::DrawWebVr");
992 // Don't need face culling, depth testing, blending, etc. Turn it all off. 1080 // Don't need face culling, depth testing, blending, etc. Turn it all off.
993 glDisable(GL_CULL_FACE); 1081 glDisable(GL_CULL_FACE);
994 glDepthMask(GL_FALSE); 1082 glDepthMask(GL_FALSE);
995 glDisable(GL_DEPTH_TEST); 1083 glDisable(GL_DEPTH_TEST);
996 glDisable(GL_SCISSOR_TEST); 1084 glDisable(GL_SCISSOR_TEST);
997 glDisable(GL_BLEND); 1085 glDisable(GL_BLEND);
998 glDisable(GL_POLYGON_OFFSET_FILL); 1086 glDisable(GL_POLYGON_OFFSET_FILL);
999 1087
1000 glViewport(0, 0, render_size_primary_.width, render_size_primary_.height); 1088 glViewport(0, 0, webvr_surface_size_.width, webvr_surface_size_.height);
1001 vr_shell_renderer_->GetWebVrRenderer()->Draw(webvr_texture_id_); 1089 vr_shell_renderer_->GetWebVrRenderer()->Draw(webvr_texture_id_);
1002 } 1090 }
1003 1091
1004 void VrShellGl::OnTriggerEvent() { 1092 void VrShellGl::OnTriggerEvent() {
1005 // Set a flag to handle this on the render thread at the next frame. 1093 // Set a flag to handle this on the render thread at the next frame.
1006 touch_pending_ = true; 1094 touch_pending_ = true;
1007 } 1095 }
1008 1096
1009 void VrShellGl::OnPause() { 1097 void VrShellGl::OnPause() {
1010 vsync_task_.Cancel(); 1098 vsync_task_.Cancel();
(...skipping 10 matching lines...) Expand all
1021 OnVSync(); 1109 OnVSync();
1022 } 1110 }
1023 } 1111 }
1024 1112
1025 void VrShellGl::SetWebVrMode(bool enabled) { 1113 void VrShellGl::SetWebVrMode(bool enabled) {
1026 web_vr_mode_ = enabled; 1114 web_vr_mode_ = enabled;
1027 } 1115 }
1028 1116
1029 void VrShellGl::UpdateWebVRTextureBounds(int16_t frame_index, 1117 void VrShellGl::UpdateWebVRTextureBounds(int16_t frame_index,
1030 const gvr::Rectf& left_bounds, 1118 const gvr::Rectf& left_bounds,
1031 const gvr::Rectf& right_bounds) { 1119 const gvr::Rectf& right_bounds,
1120 const gvr::Sizei& source_size) {
1032 if (frame_index < 0) { 1121 if (frame_index < 0) {
1033 webvr_left_viewport_->SetSourceUv(left_bounds); 1122 webvr_left_viewport_->SetSourceUv(left_bounds);
1034 webvr_right_viewport_->SetSourceUv(right_bounds); 1123 webvr_right_viewport_->SetSourceUv(right_bounds);
1035 } else { 1124 } else {
1036 pending_bounds_.emplace( 1125 pending_bounds_.emplace(std::make_pair(
dcheng 2017/03/08 07:23:40 std::make_pair should be unnecessary with emplace
klausw 2017/03/08 08:11:09 Done.
1037 std::make_pair(frame_index, std::make_pair(left_bounds, right_bounds))); 1126 frame_index, WebVrBounds(left_bounds, right_bounds, source_size)));
1038 } 1127 }
1039 } 1128 }
1040 1129
1041 void VrShellGl::ContentBoundsChanged(int width, int height) { 1130 void VrShellGl::ContentBoundsChanged(int width, int height) {
1042 TRACE_EVENT0("gpu", "VrShellGl::ContentBoundsChanged"); 1131 TRACE_EVENT0("gpu", "VrShellGl::ContentBoundsChanged");
1043 content_tex_css_width_ = width; 1132 content_tex_css_width_ = width;
1044 content_tex_css_height_ = height; 1133 content_tex_css_height_ = height;
1045 } 1134 }
1046 1135
1047 void VrShellGl::ContentPhysicalBoundsChanged(int width, int height) { 1136 void VrShellGl::ContentPhysicalBoundsChanged(int width, int height) {
(...skipping 13 matching lines...) Expand all
1061 ui_surface_texture_->SetDefaultBufferSize(width, height); 1150 ui_surface_texture_->SetDefaultBufferSize(width, height);
1062 ui_tex_physical_size_.width = width; 1151 ui_tex_physical_size_.width = width;
1063 ui_tex_physical_size_.height = height; 1152 ui_tex_physical_size_.height = height;
1064 } 1153 }
1065 1154
1066 base::WeakPtr<VrShellGl> VrShellGl::GetWeakPtr() { 1155 base::WeakPtr<VrShellGl> VrShellGl::GetWeakPtr() {
1067 return weak_ptr_factory_.GetWeakPtr(); 1156 return weak_ptr_factory_.GetWeakPtr();
1068 } 1157 }
1069 1158
1070 void VrShellGl::OnVSync() { 1159 void VrShellGl::OnVSync() {
1160 while (premature_received_frames_ > 0) {
1161 TRACE_EVENT0("gpu", "VrShellGl::OnWebVRFrameAvailableRetry");
1162 --premature_received_frames_;
1163 OnWebVRFrameAvailable();
1164 }
1165
1071 base::TimeTicks now = base::TimeTicks::Now(); 1166 base::TimeTicks now = base::TimeTicks::Now();
1072 base::TimeTicks target; 1167 base::TimeTicks target;
1073 1168
1074 // Don't send VSyncs until we have a timebase/interval. 1169 // Don't send VSyncs until we have a timebase/interval.
1075 if (vsync_interval_.is_zero()) 1170 if (vsync_interval_.is_zero())
1076 return; 1171 return;
1077 target = now + vsync_interval_; 1172 target = now + vsync_interval_;
1078 int64_t intervals = (target - vsync_timebase_) / vsync_interval_; 1173 int64_t intervals = (target - vsync_timebase_) / vsync_interval_;
1079 target = vsync_timebase_ + intervals * vsync_interval_; 1174 target = vsync_timebase_ + intervals * vsync_interval_;
1080 task_runner_->PostDelayedTask(FROM_HERE, vsync_task_.callback(), 1175 task_runner_->PostDelayedTask(FROM_HERE, vsync_task_.callback(),
1081 target - now); 1176 target - now);
1082 1177
1083 base::TimeDelta time = intervals * vsync_interval_; 1178 base::TimeDelta time = intervals * vsync_interval_;
1084 if (!callback_.is_null()) { 1179 if (!callback_.is_null()) {
1085 SendVSync(time, base::ResetAndReturn(&callback_)); 1180 SendVSync(time, base::ResetAndReturn(&callback_));
1086 } else { 1181 } else {
1087 pending_vsync_ = true; 1182 pending_vsync_ = true;
1088 pending_time_ = time; 1183 pending_time_ = time;
1089 } 1184 }
1090 DrawFrame(); 1185 if (!web_vr_mode_) {
1186 DrawFrame(-1);
1187 }
1091 } 1188 }
1092 1189
1093 void VrShellGl::OnRequest(device::mojom::VRVSyncProviderRequest request) { 1190 void VrShellGl::OnRequest(device::mojom::VRVSyncProviderRequest request) {
1094 binding_.Close(); 1191 binding_.Close();
1095 binding_.Bind(std::move(request)); 1192 binding_.Bind(std::move(request));
1096 } 1193 }
1097 1194
1098 void VrShellGl::GetVSync(const GetVSyncCallback& callback) { 1195 void VrShellGl::GetVSync(const GetVSyncCallback& callback) {
1099 if (!pending_vsync_) { 1196 if (!pending_vsync_) {
1100 if (!callback_.is_null()) { 1197 if (!callback_.is_null()) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1150 void VrShellGl::ResetPose() { 1247 void VrShellGl::ResetPose() {
1151 // Should never call RecenterTracking when using with Daydream viewers. On 1248 // Should never call RecenterTracking when using with Daydream viewers. On
1152 // those devices recentering should only be done via the controller. 1249 // those devices recentering should only be done via the controller.
1153 if (gvr_api_ && gvr_api_->GetViewerType() == GVR_VIEWER_TYPE_CARDBOARD) 1250 if (gvr_api_ && gvr_api_->GetViewerType() == GVR_VIEWER_TYPE_CARDBOARD)
1154 gvr_api_->RecenterTracking(); 1251 gvr_api_->RecenterTracking();
1155 } 1252 }
1156 1253
1157 void VrShellGl::CreateVRDisplayInfo( 1254 void VrShellGl::CreateVRDisplayInfo(
1158 const base::Callback<void(device::mojom::VRDisplayInfoPtr)>& callback, 1255 const base::Callback<void(device::mojom::VRDisplayInfoPtr)>& callback,
1159 uint32_t device_id) { 1256 uint32_t device_id) {
1257 // This assumes that the initial webvr_surface_size_ was set to the
1258 // appropriate recommended render resolution as the default size during
1259 // InitializeGl. Revisit if the initialization order changes.
1160 device::mojom::VRDisplayInfoPtr info = VrShell::CreateVRDisplayInfo( 1260 device::mojom::VRDisplayInfoPtr info = VrShell::CreateVRDisplayInfo(
1161 gvr_api_.get(), content_tex_physical_size_, device_id); 1261 gvr_api_.get(), webvr_surface_size_, device_id);
1162 main_thread_task_runner_->PostTask( 1262 main_thread_task_runner_->PostTask(
1163 FROM_HERE, 1263 FROM_HERE,
1164 base::Bind(&RunVRDisplayInfoCallback, callback, base::Passed(&info))); 1264 base::Bind(&RunVRDisplayInfoCallback, callback, base::Passed(&info)));
1165 } 1265 }
1166 1266
1167 } // namespace vr_shell 1267 } // namespace vr_shell
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698