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

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

Issue 2624633002: Remove Sync GetPose VRService call, implement VRVSyncProvider (Closed)
Patch Set: Address comments Created 3 years, 11 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 "base/android/jni_android.h" 7 #include "base/android/jni_android.h"
8 #include "base/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
9 #include "base/metrics/histogram_macros.h" 9 #include "base/metrics/histogram_macros.h"
10 #include "base/threading/thread_task_runner_handle.h" 10 #include "base/threading/thread_task_runner_handle.h"
11 #include "chrome/browser/android/vr_shell/ui_elements.h" 11 #include "chrome/browser/android/vr_shell/ui_elements.h"
12 #include "chrome/browser/android/vr_shell/ui_scene.h" 12 #include "chrome/browser/android/vr_shell/ui_scene.h"
13 #include "chrome/browser/android/vr_shell/vr_controller.h" 13 #include "chrome/browser/android/vr_shell/vr_controller.h"
14 #include "chrome/browser/android/vr_shell/vr_gl_util.h" 14 #include "chrome/browser/android/vr_shell/vr_gl_util.h"
15 #include "chrome/browser/android/vr_shell/vr_input_manager.h" 15 #include "chrome/browser/android/vr_shell/vr_input_manager.h"
16 #include "chrome/browser/android/vr_shell/vr_math.h" 16 #include "chrome/browser/android/vr_shell/vr_math.h"
17 #include "chrome/browser/android/vr_shell/vr_shell.h" 17 #include "chrome/browser/android/vr_shell/vr_shell.h"
18 #include "chrome/browser/android/vr_shell/vr_shell_renderer.h" 18 #include "chrome/browser/android/vr_shell/vr_shell_renderer.h"
19 #include "device/vr/android/gvr/gvr_device.h"
19 #include "third_party/WebKit/public/platform/WebInputEvent.h" 20 #include "third_party/WebKit/public/platform/WebInputEvent.h"
20 #include "ui/gfx/vsync_provider.h"
21 #include "ui/gl/android/scoped_java_surface.h" 21 #include "ui/gl/android/scoped_java_surface.h"
22 #include "ui/gl/android/surface_texture.h" 22 #include "ui/gl/android/surface_texture.h"
23 #include "ui/gl/gl_bindings.h" 23 #include "ui/gl/gl_bindings.h"
24 #include "ui/gl/gl_context.h" 24 #include "ui/gl/gl_context.h"
25 #include "ui/gl/gl_surface.h" 25 #include "ui/gl/gl_surface.h"
26 #include "ui/gl/init/gl_factory.h" 26 #include "ui/gl/init/gl_factory.h"
27 27
28 namespace vr_shell { 28 namespace vr_shell {
29 29
30 namespace { 30 namespace {
31 // Constant taken from treasure_hunt demo. 31 // TODO(mthiesse): If gvr::PlatformInfo().GetPosePredictionTime() is ever
32 // exposed, use that instead (it defaults to 50ms on most platforms).
32 static constexpr long kPredictionTimeWithoutVsyncNanos = 50000000; 33 static constexpr long kPredictionTimeWithoutVsyncNanos = 50000000;
33 34
34 static constexpr float kZNear = 0.1f; 35 static constexpr float kZNear = 0.1f;
35 static constexpr float kZFar = 1000.0f; 36 static constexpr float kZFar = 1000.0f;
36 37
37 // Screen angle in degrees. 0 = vertical, positive = top closer. 38 // Screen angle in degrees. 0 = vertical, positive = top closer.
38 static constexpr float kDesktopScreenTiltDefault = 0; 39 static constexpr float kDesktopScreenTiltDefault = 0;
39 40
40 static constexpr float kReticleWidth = 0.025f; 41 static constexpr float kReticleWidth = 0.025f;
41 static constexpr float kReticleHeight = 0.025f; 42 static constexpr float kReticleHeight = 0.025f;
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 return mouse_event; 134 return mouse_event;
134 } 135 }
135 136
136 enum class ViewerType { 137 enum class ViewerType {
137 UNKNOWN_TYPE = 0, 138 UNKNOWN_TYPE = 0,
138 CARDBOARD = 1, 139 CARDBOARD = 1,
139 DAYDREAM = 2, 140 DAYDREAM = 2,
140 VIEWER_TYPE_MAX, 141 VIEWER_TYPE_MAX,
141 }; 142 };
142 143
143 int GetPixelEncodedPoseIndexByte() {
144 TRACE_EVENT0("gpu", "VrShellGl::GetPixelEncodedPoseIndex");
145 // Read the pose index encoded in a bottom left pixel as color values.
146 // See also third_party/WebKit/Source/modules/vr/VRDisplay.cpp which
147 // encodes the pose index, and device/vr/android/gvr/gvr_device.cc
148 // which tracks poses. Returns the low byte (0..255) if valid, or -1
149 // if not valid due to bad magic number.
150 uint8_t pixels[4];
151 // Assume we're reading from the framebuffer we just wrote to.
152 // That's true currently, we may need to use glReadBuffer(GL_BACK)
153 // or equivalent if the rendering setup changes in the future.
154 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
155
156 // Check for the magic number written by VRDevice.cpp on submit.
157 // This helps avoid glitches from garbage data in the render
158 // buffer that can appear during initialization or resizing. These
159 // often appear as flashes of all-black or all-white pixels.
160 if (pixels[1] == kWebVrPosePixelMagicNumbers[0] &&
161 pixels[2] == kWebVrPosePixelMagicNumbers[1]) {
162 // Pose is good.
163 return pixels[0];
164 }
165 VLOG(1) << "WebVR: reject decoded pose index " << (int)pixels[0] <<
166 ", bad magic number " << (int)pixels[1] << ", " << (int)pixels[2];
167 return -1;
168 }
169
170 int64_t TimeInMicroseconds() { 144 int64_t TimeInMicroseconds() {
171 return std::chrono::duration_cast<std::chrono::microseconds>( 145 return std::chrono::duration_cast<std::chrono::microseconds>(
172 std::chrono::steady_clock::now().time_since_epoch()).count(); 146 std::chrono::steady_clock::now().time_since_epoch()).count();
173 } 147 }
174 148
175 void WaitForSwapAck(const base::Closure& callback, gfx::SwapResult result) {
176 callback.Run();
177 }
178
179 } // namespace 149 } // namespace
180 150
181 VrShellGl::VrShellGl( 151 VrShellGl::VrShellGl(
182 const base::WeakPtr<VrShell>& weak_vr_shell, 152 const base::WeakPtr<VrShell>& weak_vr_shell,
183 const base::WeakPtr<VrInputManager>& content_input_manager, 153 const base::WeakPtr<VrInputManager>& content_input_manager,
184 const base::WeakPtr<VrInputManager>& ui_input_manager, 154 const base::WeakPtr<VrInputManager>& ui_input_manager,
185 scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner, 155 scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
186 gvr_context* gvr_api, 156 gvr_context* gvr_api,
187 bool initially_web_vr, 157 bool initially_web_vr,
188 bool reprojected_rendering) 158 bool reprojected_rendering)
189 : web_vr_mode_(initially_web_vr), 159 : web_vr_mode_(initially_web_vr),
190 surfaceless_rendering_(reprojected_rendering), 160 surfaceless_rendering_(reprojected_rendering),
191 task_runner_(base::ThreadTaskRunnerHandle::Get()), 161 task_runner_(base::ThreadTaskRunnerHandle::Get()),
162 binding_(this),
192 weak_vr_shell_(weak_vr_shell), 163 weak_vr_shell_(weak_vr_shell),
193 content_input_manager_(content_input_manager), 164 content_input_manager_(content_input_manager),
194 ui_input_manager_(ui_input_manager), 165 ui_input_manager_(ui_input_manager),
195 main_thread_task_runner_(std::move(main_thread_task_runner)), 166 main_thread_task_runner_(std::move(main_thread_task_runner)),
196 weak_ptr_factory_(this) { 167 weak_ptr_factory_(this) {
197 GvrInit(gvr_api); 168 GvrInit(gvr_api);
198 } 169 }
199 170
200 VrShellGl::~VrShellGl() { 171 VrShellGl::~VrShellGl() {
201 draw_task_.Cancel(); 172 vsync_task_.Cancel();
173 if (!callback_.is_null())
174 callback_.Run(nullptr, 0);
202 } 175 }
203 176
204 void VrShellGl::Initialize() { 177 void VrShellGl::Initialize() {
205 gvr::Mat4f identity;
206 SetIdentityM(identity);
207 webvr_head_pose_.resize(kPoseRingBufferSize, identity);
208 webvr_head_pose_valid_.resize(kPoseRingBufferSize, false);
209
210 scene_.reset(new UiScene); 178 scene_.reset(new UiScene);
211 179
212 if (surfaceless_rendering_) { 180 if (surfaceless_rendering_) {
213 // If we're rendering surfaceless, we'll never get a java surface to render 181 // If we're rendering surfaceless, we'll never get a java surface to render
214 // into, so we can initialize GL right away. 182 // into, so we can initialize GL right away.
215 InitializeGl(nullptr); 183 InitializeGl(nullptr);
216 } 184 }
217 } 185 }
218 186
219 void VrShellGl::InitializeGl(gfx::AcceleratedWidget window) { 187 void VrShellGl::InitializeGl(gfx::AcceleratedWidget window) {
(...skipping 22 matching lines...) Expand all
242 LOG(ERROR) << "gl::init::CreateGLContext failed"; 210 LOG(ERROR) << "gl::init::CreateGLContext failed";
243 ForceExitVr(); 211 ForceExitVr();
244 return; 212 return;
245 } 213 }
246 if (!context_->MakeCurrent(surface_.get())) { 214 if (!context_->MakeCurrent(surface_.get())) {
247 LOG(ERROR) << "gl::GLContext::MakeCurrent() failed"; 215 LOG(ERROR) << "gl::GLContext::MakeCurrent() failed";
248 ForceExitVr(); 216 ForceExitVr();
249 return; 217 return;
250 } 218 }
251 219
252 // TODO(mthiesse): We don't appear to have a VSync provider ever here. This is
253 // sort of okay, because the GVR swap chain will block if we render too fast,
254 // but we should address this properly.
255 if (surface_->GetVSyncProvider()) {
256 surface_->GetVSyncProvider()->GetVSyncParameters(base::Bind(
257 &VrShellGl::UpdateVSyncParameters, weak_ptr_factory_.GetWeakPtr()));
258 } else {
259 LOG(ERROR) << "No VSync Provider";
260 }
261
262 unsigned int textures[2]; 220 unsigned int textures[2];
263 glGenTextures(2, textures); 221 glGenTextures(2, textures);
264 ui_texture_id_ = textures[0]; 222 ui_texture_id_ = textures[0];
265 content_texture_id_ = textures[1]; 223 content_texture_id_ = textures[1];
266 ui_surface_texture_ = gl::SurfaceTexture::Create(ui_texture_id_); 224 ui_surface_texture_ = gl::SurfaceTexture::Create(ui_texture_id_);
267 content_surface_texture_ = gl::SurfaceTexture::Create(content_texture_id_); 225 content_surface_texture_ = gl::SurfaceTexture::Create(content_texture_id_);
268 ui_surface_.reset(new gl::ScopedJavaSurface(ui_surface_texture_.get())); 226 ui_surface_.reset(new gl::ScopedJavaSurface(ui_surface_texture_.get()));
269 content_surface_.reset(new gl::ScopedJavaSurface( 227 content_surface_.reset(new gl::ScopedJavaSurface(
270 content_surface_texture_.get())); 228 content_surface_texture_.get()));
271 ui_surface_texture_->SetFrameAvailableCallback(base::Bind( 229 ui_surface_texture_->SetFrameAvailableCallback(base::Bind(
272 &VrShellGl::OnUIFrameAvailable, weak_ptr_factory_.GetWeakPtr())); 230 &VrShellGl::OnUIFrameAvailable, weak_ptr_factory_.GetWeakPtr()));
273 content_surface_texture_->SetFrameAvailableCallback(base::Bind( 231 content_surface_texture_->SetFrameAvailableCallback(base::Bind(
274 &VrShellGl::OnContentFrameAvailable, weak_ptr_factory_.GetWeakPtr())); 232 &VrShellGl::OnContentFrameAvailable, weak_ptr_factory_.GetWeakPtr()));
275 233
276 content_surface_texture_->SetDefaultBufferSize( 234 content_surface_texture_->SetDefaultBufferSize(
277 content_tex_physical_size_.width, content_tex_physical_size_.height); 235 content_tex_physical_size_.width, content_tex_physical_size_.height);
278 ui_surface_texture_->SetDefaultBufferSize(ui_tex_physical_size_.width, 236 ui_surface_texture_->SetDefaultBufferSize(ui_tex_physical_size_.width,
279 ui_tex_physical_size_.height); 237 ui_tex_physical_size_.height);
280 238
281 main_thread_task_runner_->PostTask(FROM_HERE, base::Bind( 239 main_thread_task_runner_->PostTask(FROM_HERE, base::Bind(
282 &VrShell::SurfacesChanged, weak_vr_shell_, 240 &VrShell::SurfacesChanged, weak_vr_shell_,
283 content_surface_->j_surface().obj(), 241 content_surface_->j_surface().obj(),
284 ui_surface_->j_surface().obj())); 242 ui_surface_->j_surface().obj()));
285 243
286 InitializeRenderer(); 244 InitializeRenderer();
287 245
288 draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this))); 246 vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this)));
289 ScheduleNextDrawFrame(); 247 OnVSync();
290 248
291 ready_to_draw_ = true; 249 ready_to_draw_ = true;
292 } 250 }
293 251
294 void VrShellGl::OnUIFrameAvailable() { 252 void VrShellGl::OnUIFrameAvailable() {
295 ui_surface_texture_->UpdateTexImage(); 253 ui_surface_texture_->UpdateTexImage();
296 } 254 }
297 255
298 void VrShellGl::OnContentFrameAvailable() { 256 void VrShellGl::OnContentFrameAvailable() {
299 content_surface_texture_->UpdateTexImage(); 257 content_surface_texture_->UpdateTexImage();
258 received_frame_ = true;
259 }
260
261 bool VrShellGl::GetPixelEncodedPoseIndexByte(int* pose_index) {
262 TRACE_EVENT0("gpu", "VrShellGl::GetPixelEncodedPoseIndex");
263 if (!received_frame_) {
264 *pose_index = last_pose_;
265 return true;
266 }
267 received_frame_ = false;
268
269 // Read the pose index encoded in a bottom left pixel as color values.
270 // See also third_party/WebKit/Source/modules/vr/VRDisplay.cpp which
271 // encodes the pose index, and device/vr/android/gvr/gvr_device.cc
272 // which tracks poses. Returns the low byte (0..255) if valid, or -1
273 // if not valid due to bad magic number.
274 uint8_t pixels[4];
275 // Assume we're reading from the framebuffer we just wrote to.
276 // That's true currently, we may need to use glReadBuffer(GL_BACK)
277 // or equivalent if the rendering setup changes in the future.
278 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
279
280 // Check for the magic number written by VRDevice.cpp on submit.
281 // This helps avoid glitches from garbage data in the render
282 // buffer that can appear during initialization or resizing. These
283 // often appear as flashes of all-black or all-white pixels.
284 if (pixels[1] == kWebVrPosePixelMagicNumbers[0] &&
285 pixels[2] == kWebVrPosePixelMagicNumbers[1]) {
286 // Pose is good.
287 *pose_index = pixels[0];
288 last_pose_ = pixels[0];
289 return true;
290 }
291 VLOG(1) << "WebVR: reject decoded pose index " << (int)pixels[0]
292 << ", bad magic number " << (int)pixels[1] << ", "
293 << (int)pixels[2];
294 return false;
300 } 295 }
301 296
302 void VrShellGl::GvrInit(gvr_context* gvr_api) { 297 void VrShellGl::GvrInit(gvr_context* gvr_api) {
303 gvr_api_ = gvr::GvrApi::WrapNonOwned(gvr_api); 298 gvr_api_ = gvr::GvrApi::WrapNonOwned(gvr_api);
304 controller_.reset(new VrController(gvr_api)); 299 controller_.reset(new VrController(gvr_api));
305 300
306 ViewerType viewerType; 301 ViewerType viewerType;
307 switch (gvr_api_->GetViewerType()) { 302 switch (gvr_api_->GetViewerType()) {
308 case gvr::ViewerType::GVR_VIEWER_TYPE_DAYDREAM: 303 case gvr::ViewerType::GVR_VIEWER_TYPE_DAYDREAM:
309 viewerType = ViewerType::DAYDREAM; 304 viewerType = ViewerType::DAYDREAM;
310 break; 305 break;
311 case gvr::ViewerType::GVR_VIEWER_TYPE_CARDBOARD: 306 case gvr::ViewerType::GVR_VIEWER_TYPE_CARDBOARD:
312 viewerType = ViewerType::CARDBOARD; 307 viewerType = ViewerType::CARDBOARD;
313 break; 308 break;
314 default: 309 default:
315 NOTREACHED(); 310 NOTREACHED();
316 viewerType = ViewerType::UNKNOWN_TYPE; 311 viewerType = ViewerType::UNKNOWN_TYPE;
317 break; 312 break;
318 } 313 }
319 UMA_HISTOGRAM_ENUMERATION("VRViewerType", static_cast<int>(viewerType), 314 UMA_HISTOGRAM_ENUMERATION("VRViewerType", static_cast<int>(viewerType),
320 static_cast<int>(ViewerType::VIEWER_TYPE_MAX)); 315 static_cast<int>(ViewerType::VIEWER_TYPE_MAX));
321 } 316 }
322 317
323 void VrShellGl::InitializeRenderer() { 318 void VrShellGl::InitializeRenderer() {
324 // While WebVR is going through the compositor path, it shares 319 // While WebVR is going through the compositor path, it shares
325 // the same texture ID. This will change once it gets its own 320 // the same texture ID. This will change once it gets its own
326 // surface, but store it separately to avoid future confusion. 321 // surface, but store it separately to avoid future confusion.
327 // TODO(klausw,crbug.com/655722): remove this. 322 // TODO(klausw,crbug.com/655722): remove this.
328 webvr_texture_id_ = content_texture_id_; 323 webvr_texture_id_ = content_texture_id_;
329 // Out of paranoia, explicitly reset the "pose valid" flags to false
330 // from the GL thread. The constructor ran in the UI thread.
331 // TODO(klausw,crbug.com/655722): remove this.
332 webvr_head_pose_valid_.assign(kPoseRingBufferSize, false);
333 324
334 gvr_api_->InitializeGl(); 325 gvr_api_->InitializeGl();
326 webvr_head_pose_.assign(kPoseRingBufferSize,
327 gvr_api_->GetHeadSpaceFromStartSpaceRotation(
328 gvr::GvrApi::GetTimePointNow()));
329
335 std::vector<gvr::BufferSpec> specs; 330 std::vector<gvr::BufferSpec> specs;
336 // For kFramePrimaryBuffer (primary VrShell and WebVR content) 331 // For kFramePrimaryBuffer (primary VrShell and WebVR content)
337 specs.push_back(gvr_api_->CreateBufferSpec()); 332 specs.push_back(gvr_api_->CreateBufferSpec());
338 render_size_primary_ = specs[kFramePrimaryBuffer].GetSize(); 333 render_size_primary_ = specs[kFramePrimaryBuffer].GetSize();
339 334
340 // For kFrameHeadlockedBuffer (for WebVR insecure content warning). 335 // For kFrameHeadlockedBuffer (for WebVR insecure content warning).
341 // Set this up at fixed resolution, the (smaller) FOV gets set below. 336 // Set this up at fixed resolution, the (smaller) FOV gets set below.
342 specs.push_back(gvr_api_->CreateBufferSpec()); 337 specs.push_back(gvr_api_->CreateBufferSpec());
343 specs.back().SetSize(kHeadlockedBufferDimensions); 338 specs.back().SetSize(kHeadlockedBufferDimensions);
344 render_size_headlocked_ = specs[kFrameHeadlockedBuffer].GetSize(); 339 render_size_headlocked_ = specs[kFrameHeadlockedBuffer].GetSize();
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 DCHECK(input_target != InputTarget::NONE); 577 DCHECK(input_target != InputTarget::NONE);
583 const base::WeakPtr<VrInputManager>& weak_ptr = 578 const base::WeakPtr<VrInputManager>& weak_ptr =
584 input_target == InputTarget::CONTENT ? content_input_manager_ 579 input_target == InputTarget::CONTENT ? content_input_manager_
585 : ui_input_manager_; 580 : ui_input_manager_;
586 main_thread_task_runner_->PostTask( 581 main_thread_task_runner_->PostTask(
587 FROM_HERE, 582 FROM_HERE,
588 base::Bind(&VrInputManager::ProcessUpdatedGesture, weak_ptr, 583 base::Bind(&VrInputManager::ProcessUpdatedGesture, weak_ptr,
589 base::Passed(std::move(event)))); 584 base::Passed(std::move(event))));
590 } 585 }
591 586
592 void VrShellGl::SetGvrPoseForWebVr(const gvr::Mat4f& pose, uint32_t pose_num) {
593 webvr_head_pose_[pose_num % kPoseRingBufferSize] = pose;
594 webvr_head_pose_valid_[pose_num % kPoseRingBufferSize] = true;
595 }
596
597 bool VrShellGl::WebVrPoseByteIsValid(int pose_index_byte) {
598 if (pose_index_byte < 0) {
599 return false;
600 }
601 if (!webvr_head_pose_valid_[pose_index_byte % kPoseRingBufferSize]) {
602 VLOG(1) << "WebVR: reject decoded pose index " << pose_index_byte <<
603 ", not a valid pose";
604 return false;
605 }
606 return true;
607 }
608
609 void VrShellGl::DrawFrame() { 587 void VrShellGl::DrawFrame() {
610 TRACE_EVENT0("gpu", "VrShellGl::DrawFrame"); 588 TRACE_EVENT0("gpu", "VrShellGl::DrawFrame");
589
611 // Reset the viewport list to just the pair of viewports for the 590 // Reset the viewport list to just the pair of viewports for the
612 // primary buffer each frame. Head-locked viewports get added by 591 // primary buffer each frame. Head-locked viewports get added by
613 // DrawVrShell if needed. 592 // DrawVrShell if needed.
614 buffer_viewport_list_->SetToRecommendedBufferViewports(); 593 buffer_viewport_list_->SetToRecommendedBufferViewports();
615 594
616 gvr::Frame frame = swap_chain_->AcquireFrame(); 595 gvr::Frame frame = swap_chain_->AcquireFrame();
617 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); 596 if (!frame.is_valid()) {
618 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; 597 return;
598 }
599 frame.BindBuffer(kFramePrimaryBuffer);
600 if (web_vr_mode_) {
601 DrawWebVr();
602 }
619 603
620 gvr::Mat4f head_pose = 604 int pose_index;
621 gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time); 605 gvr::Mat4f head_pose;
606
607 // When using async reprojection, we need to know which pose was used in
608 // the WebVR app for drawing this frame. Due to unknown amounts of
609 // buffering in the compositor and SurfaceTexture, we read the pose number
610 // from a corner pixel. There's no point in doing this for legacy
611 // distortion rendering since that doesn't need a pose, and reading back
612 // pixels is an expensive operation. TODO(klausw,crbug.com/655722): stop
613 // doing this once we have working no-compositor rendering for WebVR.
614 if (web_vr_mode_ && gvr_api_->GetAsyncReprojectionEnabled() &&
615 GetPixelEncodedPoseIndexByte(&pose_index)) {
616 head_pose = webvr_head_pose_[pose_index % kPoseRingBufferSize];
617 } else {
618 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow();
619 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos;
620 head_pose = gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time);
621 }
622 622
623 gvr::Vec3f position = GetTranslation(head_pose); 623 gvr::Vec3f position = GetTranslation(head_pose);
624 if (position.x == 0.0f && position.y == 0.0f && position.z == 0.0f) { 624 if (position.x == 0.0f && position.y == 0.0f && position.z == 0.0f) {
625 // This appears to be a 3DOF pose without a neck model. Add one. 625 // This appears to be a 3DOF pose without a neck model. Add one.
626 // The head pose has redundant data. Assume we're only using the 626 // The head pose has redundant data. Assume we're only using the
627 // object_from_reference_matrix, we're not updating position_external. 627 // object_from_reference_matrix, we're not updating position_external.
628 // TODO: Not sure what object_from_reference_matrix is. The new api removed 628 // TODO: Not sure what object_from_reference_matrix is. The new api removed
629 // it. For now, removing it seems working fine. 629 // it. For now, removing it seems working fine.
630 gvr_api_->ApplyNeckModel(head_pose, 1.0f); 630 gvr_api_->ApplyNeckModel(head_pose, 1.0f);
631 } 631 }
632 632
633 frame.BindBuffer(kFramePrimaryBuffer);
634
635 // Update the render position of all UI elements (including desktop). 633 // Update the render position of all UI elements (including desktop).
636 const float screen_tilt = kDesktopScreenTiltDefault * M_PI / 180.0f; 634 const float screen_tilt = kDesktopScreenTiltDefault * M_PI / 180.0f;
637 scene_->UpdateTransforms(screen_tilt, TimeInMicroseconds()); 635 scene_->UpdateTransforms(screen_tilt, TimeInMicroseconds());
638 636
639 UpdateController(GetForwardVector(head_pose)); 637 UpdateController(GetForwardVector(head_pose));
640 638
641 if (web_vr_mode_) {
642 DrawWebVr();
643
644 // When using async reprojection, we need to know which pose was used in
645 // the WebVR app for drawing this frame. Due to unknown amounts of
646 // buffering in the compositor and SurfaceTexture, we read the pose number
647 // from a corner pixel. There's no point in doing this for legacy
648 // distortion rendering since that doesn't need a pose, and reading back
649 // pixels is an expensive operation. TODO(klausw,crbug.com/655722): stop
650 // doing this once we have working no-compositor rendering for WebVR.
651 if (gvr_api_->GetAsyncReprojectionEnabled()) {
652 int pose_index_byte = GetPixelEncodedPoseIndexByte();
653 if (WebVrPoseByteIsValid(pose_index_byte)) {
654 // We have a valid pose, use it for reprojection.
655 webvr_left_viewport_->SetReprojection(GVR_REPROJECTION_FULL);
656 webvr_right_viewport_->SetReprojection(GVR_REPROJECTION_FULL);
657 head_pose = webvr_head_pose_[pose_index_byte % kPoseRingBufferSize];
658 // We can't mark the used pose as invalid since unfortunately
659 // we have to reuse them. The compositor will re-submit stale
660 // frames on vsync, and we can't tell that this has happened
661 // until we've read the pose index from it, and at that point
662 // it's too late to skip rendering.
663 } else {
664 // If we don't get a valid frame ID back we shouldn't attempt
665 // to reproject by an invalid matrix, so turn off reprojection
666 // instead. Invalid poses can permanently break reprojection
667 // for this GVR instance: http://crbug.com/667327
668 webvr_left_viewport_->SetReprojection(GVR_REPROJECTION_NONE);
669 webvr_right_viewport_->SetReprojection(GVR_REPROJECTION_NONE);
670 }
671 }
672 }
673
674 DrawVrShell(head_pose, frame); 639 DrawVrShell(head_pose, frame);
675 640
676 frame.Unbind(); 641 frame.Unbind();
677 frame.Submit(*buffer_viewport_list_, head_pose); 642 frame.Submit(*buffer_viewport_list_, head_pose);
678 643
679 // No need to swap buffers for surfaceless rendering. 644 // No need to swap buffers for surfaceless rendering.
680 if (surfaceless_rendering_) { 645 if (!surfaceless_rendering_) {
681 ScheduleNextDrawFrame(); 646 // TODO(mthiesse): Support asynchronous SwapBuffers.
682 return;
683 }
684
685 if (surface_->SupportsAsyncSwap()) {
686 surface_->SwapBuffersAsync(base::Bind(&WaitForSwapAck, base::Bind(
687 &VrShellGl::ScheduleNextDrawFrame, weak_ptr_factory_.GetWeakPtr())));
688 } else {
689 surface_->SwapBuffers(); 647 surface_->SwapBuffers();
690 ScheduleNextDrawFrame();
691 } 648 }
692 } 649 }
693 650
694 void VrShellGl::DrawVrShell(const gvr::Mat4f& head_pose, 651 void VrShellGl::DrawVrShell(const gvr::Mat4f& head_pose,
695 gvr::Frame &frame) { 652 gvr::Frame &frame) {
696 TRACE_EVENT0("gpu", "VrShellGl::DrawVrShell"); 653 TRACE_EVENT0("gpu", "VrShellGl::DrawVrShell");
697 std::vector<const ContentRectangle*> head_locked_elements; 654 std::vector<const ContentRectangle*> head_locked_elements;
698 std::vector<const ContentRectangle*> world_elements; 655 std::vector<const ContentRectangle*> world_elements;
699 for (const auto& rect : scene_->GetUiElements()) { 656 for (const auto& rect : scene_->GetUiElements()) {
700 if (!rect->IsVisible()) 657 if (!rect->IsVisible())
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 buffer_viewport_list_->SetBufferViewport(GVR_RIGHT_EYE, 860 buffer_viewport_list_->SetBufferViewport(GVR_RIGHT_EYE,
904 *webvr_right_viewport_); 861 *webvr_right_viewport_);
905 } 862 }
906 863
907 void VrShellGl::OnTriggerEvent() { 864 void VrShellGl::OnTriggerEvent() {
908 // Set a flag to handle this on the render thread at the next frame. 865 // Set a flag to handle this on the render thread at the next frame.
909 touch_pending_ = true; 866 touch_pending_ = true;
910 } 867 }
911 868
912 void VrShellGl::OnPause() { 869 void VrShellGl::OnPause() {
913 draw_task_.Cancel(); 870 vsync_task_.Cancel();
914 controller_->OnPause(); 871 controller_->OnPause();
915 gvr_api_->PauseTracking(); 872 gvr_api_->PauseTracking();
916 } 873 }
917 874
918 void VrShellGl::OnResume() { 875 void VrShellGl::OnResume() {
919 gvr_api_->RefreshViewerProfile(); 876 gvr_api_->RefreshViewerProfile();
920 gvr_api_->ResumeTracking(); 877 gvr_api_->ResumeTracking();
921 controller_->OnResume(); 878 controller_->OnResume();
922 if (ready_to_draw_) { 879 if (ready_to_draw_) {
923 draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this))); 880 vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this)));
924 ScheduleNextDrawFrame(); 881 OnVSync();
925 } 882 }
926 } 883 }
927 884
928 void VrShellGl::SetWebVrMode(bool enabled) { 885 void VrShellGl::SetWebVrMode(bool enabled) {
929 web_vr_mode_ = enabled; 886 web_vr_mode_ = enabled;
930 } 887 }
931 888
932 void VrShellGl::UpdateWebVRTextureBounds(const gvr::Rectf& left_bounds, 889 void VrShellGl::UpdateWebVRTextureBounds(const gvr::Rectf& left_bounds,
933 const gvr::Rectf& right_bounds) { 890 const gvr::Rectf& right_bounds) {
934 webvr_left_viewport_->SetSourceUv(left_bounds); 891 webvr_left_viewport_->SetSourceUv(left_bounds);
(...skipping 26 matching lines...) Expand all
961 if (ui_surface_texture_.get()) 918 if (ui_surface_texture_.get())
962 ui_surface_texture_->SetDefaultBufferSize(width, height); 919 ui_surface_texture_->SetDefaultBufferSize(width, height);
963 ui_tex_physical_size_.width = width; 920 ui_tex_physical_size_.width = width;
964 ui_tex_physical_size_.height = height; 921 ui_tex_physical_size_.height = height;
965 } 922 }
966 923
967 base::WeakPtr<VrShellGl> VrShellGl::GetWeakPtr() { 924 base::WeakPtr<VrShellGl> VrShellGl::GetWeakPtr() {
968 return weak_ptr_factory_.GetWeakPtr(); 925 return weak_ptr_factory_.GetWeakPtr();
969 } 926 }
970 927
971 void VrShellGl::UpdateVSyncParameters(const base::TimeTicks timebase, 928 void VrShellGl::OnVSync() {
972 const base::TimeDelta interval) {
973 vsync_timebase_ = timebase;
974 vsync_interval_ = interval;
975 }
976
977 void VrShellGl::ScheduleNextDrawFrame() {
978 base::TimeTicks now = base::TimeTicks::Now(); 929 base::TimeTicks now = base::TimeTicks::Now();
979 base::TimeTicks target; 930 base::TimeTicks target;
980 931
981 if (vsync_interval_.is_zero()) { 932 // Don't send VSyncs until we have a timebase/interval.
982 target = now; 933 if (vsync_interval_.is_zero())
934 return;
935 target = now + vsync_interval_;
936 int64_t intervals = (target - vsync_timebase_) / vsync_interval_;
937 target = vsync_timebase_ + intervals * vsync_interval_;
938 task_runner_->PostDelayedTask(FROM_HERE, vsync_task_.callback(),
939 target - now);
940
941 double time = (intervals * vsync_interval_).InSecondsF();
942 if (!callback_.is_null()) {
943 callback_.Run(GetPose(), time);
944 callback_.Reset();
983 } else { 945 } else {
984 target = now + vsync_interval_; 946 pending_vsync_ = true;
985 int64_t intervals = (target - vsync_timebase_) / vsync_interval_; 947 pending_time_ = time;
986 target = vsync_timebase_ + intervals * vsync_interval_;
987 } 948 }
949 DrawFrame();
950 }
988 951
989 task_runner_->PostDelayedTask(FROM_HERE, draw_task_.callback(), target - now); 952 void VrShellGl::OnRequest(device::mojom::VRVSyncProviderRequest request) {
953 binding_.Close();
954 binding_.Bind(std::move(request));
955 }
956
957 void VrShellGl::GetVSync(const GetVSyncCallback& callback) {
958 if (!pending_vsync_) {
959 CHECK(callback_.is_null());
dcheng 2017/01/14 11:22:53 As this is invoked by the renderer, it's unsafe to
mthiesse 2017/01/16 20:52:57 Done.
960 callback_ = std::move(callback);
961 return;
962 }
963 pending_vsync_ = false;
964 callback.Run(GetPose(), pending_time_);
965 }
966
967 void VrShellGl::UpdateVSyncInterval(long timebase_nanos,
968 double interval_seconds) {
969 vsync_timebase_ = base::TimeTicks();
970 vsync_timebase_ += base::TimeDelta::FromMicroseconds(timebase_nanos / 1000);
971 vsync_interval_ = base::TimeDelta::FromSecondsD(interval_seconds);
972 vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this)));
973 OnVSync();
990 } 974 }
991 975
992 void VrShellGl::ForceExitVr() { 976 void VrShellGl::ForceExitVr() {
993 main_thread_task_runner_->PostTask( 977 main_thread_task_runner_->PostTask(
994 FROM_HERE, base::Bind(&VrShell::ForceExitVr, weak_vr_shell_)); 978 FROM_HERE, base::Bind(&VrShell::ForceExitVr, weak_vr_shell_));
995 } 979 }
996 980
997 void VrShellGl::UpdateScene(std::unique_ptr<base::ListValue> commands) { 981 void VrShellGl::UpdateScene(std::unique_ptr<base::ListValue> commands) {
998 scene_->HandleCommands(std::move(commands), TimeInMicroseconds()); 982 scene_->HandleCommands(std::move(commands), TimeInMicroseconds());
999 } 983 }
1000 984
985 device::mojom::VRPosePtr VrShellGl::GetPose() {
986 TRACE_EVENT0("input", "VrShellGl::GetPose");
987
988 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow();
989 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos;
990
991 gvr::Mat4f head_mat =
992 gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time);
993 head_mat = gvr_api_->ApplyNeckModel(head_mat, 1.0f);
994
995 uint32_t pose_index = pose_index_++;
996 webvr_head_pose_[pose_index % kPoseRingBufferSize] = head_mat;
997
998 return VrShell::VRPosePtrFromGvrPose(head_mat, pose_index);
999 }
1000
1001 } // namespace vr_shell 1001 } // namespace vr_shell
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698