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

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

Issue 2616583002: Fix WebVR support for devices without Async Reprojection. (Closed)
Patch Set: 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/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
8 #include "base/metrics/histogram_macros.h" 9 #include "base/metrics/histogram_macros.h"
9 #include "base/threading/thread_task_runner_handle.h" 10 #include "base/threading/thread_task_runner_handle.h"
10 #include "chrome/browser/android/vr_shell/ui_elements.h" 11 #include "chrome/browser/android/vr_shell/ui_elements.h"
11 #include "chrome/browser/android/vr_shell/ui_scene.h" 12 #include "chrome/browser/android/vr_shell/ui_scene.h"
12 #include "chrome/browser/android/vr_shell/vr_controller.h" 13 #include "chrome/browser/android/vr_shell/vr_controller.h"
13 #include "chrome/browser/android/vr_shell/vr_gl_util.h" 14 #include "chrome/browser/android/vr_shell/vr_gl_util.h"
14 #include "chrome/browser/android/vr_shell/vr_input_manager.h" 15 #include "chrome/browser/android/vr_shell/vr_input_manager.h"
15 #include "chrome/browser/android/vr_shell/vr_math.h" 16 #include "chrome/browser/android/vr_shell/vr_math.h"
16 #include "chrome/browser/android/vr_shell/vr_shell.h" 17 #include "chrome/browser/android/vr_shell/vr_shell.h"
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 VLOG(1) << "WebVR: reject decoded pose index " << (int)pixels[0] << 167 VLOG(1) << "WebVR: reject decoded pose index " << (int)pixels[0] <<
167 ", bad magic number " << (int)pixels[1] << ", " << (int)pixels[2]; 168 ", bad magic number " << (int)pixels[1] << ", " << (int)pixels[2];
168 return -1; 169 return -1;
169 } 170 }
170 171
171 int64_t TimeInMicroseconds() { 172 int64_t TimeInMicroseconds() {
172 return std::chrono::duration_cast<std::chrono::microseconds>( 173 return std::chrono::duration_cast<std::chrono::microseconds>(
173 std::chrono::steady_clock::now().time_since_epoch()).count(); 174 std::chrono::steady_clock::now().time_since_epoch()).count();
174 } 175 }
175 176
177 void WaitForSwapAck(const base::Closure& callback, gfx::SwapResult result) {
178 callback.Run();
179 }
180
176 } // namespace 181 } // namespace
177 182
178 VrShellGl::VrShellGl( 183 VrShellGl::VrShellGl(
179 const base::WeakPtr<VrShell>& weak_vr_shell, 184 const base::WeakPtr<VrShell>& weak_vr_shell,
180 const base::WeakPtr<VrInputManager>& content_input_manager, 185 const base::WeakPtr<VrInputManager>& content_input_manager,
181 const base::WeakPtr<VrInputManager>& ui_input_manager, 186 const base::WeakPtr<VrInputManager>& ui_input_manager,
182 scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner, 187 scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
183 gvr_context* gvr_api, 188 gvr_context* gvr_api,
184 bool initially_web_vr) 189 bool initially_web_vr,
190 bool reprojected_rendering)
185 : web_vr_mode_(initially_web_vr), 191 : web_vr_mode_(initially_web_vr),
192 surfaceless_rendering_(reprojected_rendering),
186 task_runner_(base::ThreadTaskRunnerHandle::Get()), 193 task_runner_(base::ThreadTaskRunnerHandle::Get()),
187 weak_vr_shell_(weak_vr_shell), 194 weak_vr_shell_(weak_vr_shell),
188 content_input_manager_(content_input_manager), 195 content_input_manager_(content_input_manager),
189 ui_input_manager_(ui_input_manager), 196 ui_input_manager_(ui_input_manager),
190 main_thread_task_runner_(std::move(main_thread_task_runner)), 197 main_thread_task_runner_(std::move(main_thread_task_runner)),
191 weak_ptr_factory_(this) { 198 weak_ptr_factory_(this) {
192 GvrInit(gvr_api); 199 GvrInit(gvr_api);
193 } 200 }
194 201
195 VrShellGl::~VrShellGl() { 202 VrShellGl::~VrShellGl() {
196 draw_task_.Cancel(); 203 draw_task_.Cancel();
197 } 204 }
198 205
199 bool VrShellGl::Initialize() { 206 void VrShellGl::Initialize() {
200 if (!InitializeGl()) return false;
201
202 gvr::Mat4f identity; 207 gvr::Mat4f identity;
203 SetIdentityM(identity); 208 SetIdentityM(identity);
204 webvr_head_pose_.resize(kPoseRingBufferSize, identity); 209 webvr_head_pose_.resize(kPoseRingBufferSize, identity);
205 webvr_head_pose_valid_.resize(kPoseRingBufferSize, false); 210 webvr_head_pose_valid_.resize(kPoseRingBufferSize, false);
206 211
207 draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this)));
208
209 scene_.reset(new UiScene); 212 scene_.reset(new UiScene);
210 213
211 InitializeRenderer(); 214 if (surfaceless_rendering_) {
212 215 // If we're rendering surfaceless, we'll never get a java surface to render
213 ScheduleNextDrawFrame(); 216 // into, so we can initialize GL right away.
214 return true; 217 InitializeGl(nullptr);
218 }
215 } 219 }
216 220
217 bool VrShellGl::InitializeGl() { 221 void VrShellGl::InitializeGl(gfx::AcceleratedWidget window) {
222 CHECK(!ready_to_draw_);
bshe 2017/01/04 16:40:23 optional nit: rename to gl_initialized_?
mthiesse 2017/01/04 16:58:09 I think ready_to_draw_ is clearer. GL being initia
218 if (gl::GetGLImplementation() == gl::kGLImplementationNone && 223 if (gl::GetGLImplementation() == gl::kGLImplementationNone &&
219 !gl::init::InitializeGLOneOff()) { 224 !gl::init::InitializeGLOneOff()) {
220 LOG(ERROR) << "gl::init::InitializeGLOneOff failed"; 225 LOG(ERROR) << "gl::init::InitializeGLOneOff failed";
221 ForceExitVr(); 226 ForceExitVr();
222 return false; 227 return;
223 } 228 }
224 surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size()); 229 if (window) {
230 CHECK(!surfaceless_rendering_);
231 surface_ = gl::init::CreateViewGLSurface(window);
232 } else {
233 CHECK(surfaceless_rendering_);
234 surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size());
235 }
225 if (!surface_.get()) { 236 if (!surface_.get()) {
226 LOG(ERROR) << "gl::init::CreateOffscreenGLSurface failed"; 237 LOG(ERROR) << "gl::init::CreateOffscreenGLSurface failed";
227 ForceExitVr(); 238 ForceExitVr();
228 return false; 239 return;
229 } 240 }
230 context_ = gl::init::CreateGLContext(nullptr, surface_.get(), 241 context_ = gl::init::CreateGLContext(nullptr, surface_.get(),
231 gl::GLContextAttribs()); 242 gl::GLContextAttribs());
232 if (!context_.get()) { 243 if (!context_.get()) {
233 LOG(ERROR) << "gl::init::CreateGLContext failed"; 244 LOG(ERROR) << "gl::init::CreateGLContext failed";
234 ForceExitVr(); 245 ForceExitVr();
235 return false; 246 return;
236 } 247 }
237 if (!context_->MakeCurrent(surface_.get())) { 248 if (!context_->MakeCurrent(surface_.get())) {
238 LOG(ERROR) << "gl::GLContext::MakeCurrent() failed"; 249 LOG(ERROR) << "gl::GLContext::MakeCurrent() failed";
239 ForceExitVr(); 250 ForceExitVr();
240 return false; 251 return;
241 } 252 }
242 253
243 // TODO(mthiesse): We don't appear to have a VSync provider ever here. This is 254 // TODO(mthiesse): We don't appear to have a VSync provider ever here. This is
244 // sort of okay, because the GVR swap chain will block if we render too fast, 255 // sort of okay, because the GVR swap chain will block if we render too fast,
245 // but we should address this properly. 256 // but we should address this properly.
246 if (surface_->GetVSyncProvider()) { 257 if (surface_->GetVSyncProvider()) {
247 surface_->GetVSyncProvider()->GetVSyncParameters(base::Bind( 258 surface_->GetVSyncProvider()->GetVSyncParameters(base::Bind(
248 &VrShellGl::UpdateVSyncParameters, weak_ptr_factory_.GetWeakPtr())); 259 &VrShellGl::UpdateVSyncParameters, weak_ptr_factory_.GetWeakPtr()));
249 } else { 260 } else {
250 LOG(ERROR) << "No VSync Provider"; 261 LOG(ERROR) << "No VSync Provider";
(...skipping 15 matching lines...) Expand all
266 277
267 content_surface_texture_->SetDefaultBufferSize( 278 content_surface_texture_->SetDefaultBufferSize(
268 content_tex_physical_size_.width, content_tex_physical_size_.height); 279 content_tex_physical_size_.width, content_tex_physical_size_.height);
269 ui_surface_texture_->SetDefaultBufferSize(ui_tex_physical_size_.width, 280 ui_surface_texture_->SetDefaultBufferSize(ui_tex_physical_size_.width,
270 ui_tex_physical_size_.height); 281 ui_tex_physical_size_.height);
271 282
272 main_thread_task_runner_->PostTask(FROM_HERE, base::Bind( 283 main_thread_task_runner_->PostTask(FROM_HERE, base::Bind(
273 &VrShell::SurfacesChanged, weak_vr_shell_, 284 &VrShell::SurfacesChanged, weak_vr_shell_,
274 content_surface_->j_surface().obj(), 285 content_surface_->j_surface().obj(),
275 ui_surface_->j_surface().obj())); 286 ui_surface_->j_surface().obj()));
276 return true; 287
288 InitializeRenderer();
289
290 draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this)));
291 ScheduleNextDrawFrame();
292
293 ready_to_draw_ = true;
294
295 return;
bshe 2017/01/04 16:40:23 nit: remove return
mthiesse 2017/01/04 16:58:09 Done.
277 } 296 }
278 297
279 void VrShellGl::OnUIFrameAvailable() { 298 void VrShellGl::OnUIFrameAvailable() {
280 ui_surface_texture_->UpdateTexImage(); 299 ui_surface_texture_->UpdateTexImage();
281 } 300 }
282 301
283 void VrShellGl::OnContentFrameAvailable() { 302 void VrShellGl::OnContentFrameAvailable() {
284 content_surface_texture_->UpdateTexImage(); 303 content_surface_texture_->UpdateTexImage();
285 } 304 }
286 305
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 webvr_right_viewport_.get()); 398 webvr_right_viewport_.get());
380 webvr_right_viewport_->SetSourceBufferIndex(kFramePrimaryBuffer); 399 webvr_right_viewport_->SetSourceBufferIndex(kFramePrimaryBuffer);
381 400
382 main_thread_task_runner_->PostTask(FROM_HERE, base::Bind( 401 main_thread_task_runner_->PostTask(FROM_HERE, base::Bind(
383 &VrShell::GvrDelegateReady, weak_vr_shell_)); 402 &VrShell::GvrDelegateReady, weak_vr_shell_));
384 } 403 }
385 404
386 void VrShellGl::UpdateController(const gvr::Vec3f& forward_vector) { 405 void VrShellGl::UpdateController(const gvr::Vec3f& forward_vector) {
387 controller_->UpdateState(); 406 controller_->UpdateState();
388 407
389
390 // Note that button up/down state is transient, so ButtonUpHappened only 408 // Note that button up/down state is transient, so ButtonUpHappened only
391 // returns true for a single frame (and we're guaranteed not to miss it). 409 // returns true for a single frame (and we're guaranteed not to miss it).
392 if (controller_->ButtonUpHappened( 410 if (controller_->ButtonUpHappened(
393 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_APP)) { 411 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_APP)) {
394 main_thread_task_runner_->PostTask( 412 main_thread_task_runner_->PostTask(
395 FROM_HERE, base::Bind(&VrShell::AppButtonPressed, weak_vr_shell_)); 413 FROM_HERE, base::Bind(&VrShell::AppButtonPressed, weak_vr_shell_));
396 } 414 }
397 415
398 if (web_vr_mode_) { 416 if (web_vr_mode_) {
399 // Process screen touch events for Cardboard button compatibility. 417 // Process screen touch events for Cardboard button compatibility.
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 webvr_right_viewport_->SetReprojection(GVR_REPROJECTION_NONE); 675 webvr_right_viewport_->SetReprojection(GVR_REPROJECTION_NONE);
658 } 676 }
659 } 677 }
660 } 678 }
661 679
662 DrawVrShell(head_pose, frame); 680 DrawVrShell(head_pose, frame);
663 681
664 frame.Unbind(); 682 frame.Unbind();
665 frame.Submit(*buffer_viewport_list_, head_pose); 683 frame.Submit(*buffer_viewport_list_, head_pose);
666 684
667 // No need to SwapBuffers for an offscreen surface. 685 // No need to swap buffers for surfaceless rendering.
668 ScheduleNextDrawFrame(); 686 if (surfaceless_rendering_) {
687 ScheduleNextDrawFrame();
688 return;
689 }
690
691 if (surface_->SupportsAsyncSwap()) {
692 surface_->SwapBuffersAsync(base::Bind(&WaitForSwapAck, base::Bind(
693 &VrShellGl::ScheduleNextDrawFrame, weak_ptr_factory_.GetWeakPtr())));
694 } else {
695 surface_->SwapBuffers();
696 ScheduleNextDrawFrame();
697 }
669 } 698 }
670 699
671 void VrShellGl::DrawVrShell(const gvr::Mat4f& head_pose, 700 void VrShellGl::DrawVrShell(const gvr::Mat4f& head_pose,
672 gvr::Frame &frame) { 701 gvr::Frame &frame) {
673 TRACE_EVENT0("gpu", "VrShellGl::DrawVrShell"); 702 TRACE_EVENT0("gpu", "VrShellGl::DrawVrShell");
674 std::vector<const ContentRectangle*> head_locked_elements; 703 std::vector<const ContentRectangle*> head_locked_elements;
675 std::vector<const ContentRectangle*> world_elements; 704 std::vector<const ContentRectangle*> world_elements;
676 for (const auto& rect : scene_->GetUiElements()) { 705 for (const auto& rect : scene_->GetUiElements()) {
677 if (!rect->visible) { 706 if (!rect->visible) {
678 continue; 707 continue;
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 void VrShellGl::OnPause() { 919 void VrShellGl::OnPause() {
891 draw_task_.Cancel(); 920 draw_task_.Cancel();
892 controller_->OnPause(); 921 controller_->OnPause();
893 gvr_api_->PauseTracking(); 922 gvr_api_->PauseTracking();
894 } 923 }
895 924
896 void VrShellGl::OnResume() { 925 void VrShellGl::OnResume() {
897 gvr_api_->RefreshViewerProfile(); 926 gvr_api_->RefreshViewerProfile();
898 gvr_api_->ResumeTracking(); 927 gvr_api_->ResumeTracking();
899 controller_->OnResume(); 928 controller_->OnResume();
900 draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this))); 929 if (ready_to_draw_) {
901 ScheduleNextDrawFrame(); 930 draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this)));
931 ScheduleNextDrawFrame();
932 }
902 } 933 }
903 934
904 void VrShellGl::SetWebVrMode(bool enabled) { 935 void VrShellGl::SetWebVrMode(bool enabled) {
905 web_vr_mode_ = enabled; 936 web_vr_mode_ = enabled;
906 } 937 }
907 938
908 void VrShellGl::UpdateWebVRTextureBounds(const gvr::Rectf& left_bounds, 939 void VrShellGl::UpdateWebVRTextureBounds(const gvr::Rectf& left_bounds,
909 const gvr::Rectf& right_bounds) { 940 const gvr::Rectf& right_bounds) {
910 webvr_left_viewport_->SetSourceUv(left_bounds); 941 webvr_left_viewport_->SetSourceUv(left_bounds);
911 webvr_right_viewport_->SetSourceUv(right_bounds); 942 webvr_right_viewport_->SetSourceUv(right_bounds);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
968 void VrShellGl::ForceExitVr() { 999 void VrShellGl::ForceExitVr() {
969 main_thread_task_runner_->PostTask( 1000 main_thread_task_runner_->PostTask(
970 FROM_HERE, base::Bind(&VrShell::ForceExitVr, weak_vr_shell_)); 1001 FROM_HERE, base::Bind(&VrShell::ForceExitVr, weak_vr_shell_));
971 } 1002 }
972 1003
973 void VrShellGl::UpdateScene(std::unique_ptr<base::ListValue> commands) { 1004 void VrShellGl::UpdateScene(std::unique_ptr<base::ListValue> commands) {
974 scene_->HandleCommands(std::move(commands), TimeInMicroseconds()); 1005 scene_->HandleCommands(std::move(commands), TimeInMicroseconds());
975 } 1006 }
976 1007
977 } // namespace vr_shell 1008 } // namespace vr_shell
OLDNEW
« chrome/browser/android/vr_shell/vr_shell.cc ('K') | « chrome/browser/android/vr_shell/vr_shell_gl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698