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

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

Powered by Google App Engine
This is Rietveld 408576698