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