Commit 8e41e5ab authored by mthiesse's avatar mthiesse Committed by Commit bot

Fix WebVR support for devices without Async Reprojection.

Adds a java Surface to render into for devices that don't support async reprojection.

BUG=674233

Review-Url: https://codereview.chromium.org/2616583002
Cr-Commit-Position: refs/heads/master@{#441443}
parent 1ccc5796
...@@ -9,6 +9,9 @@ import android.app.Activity; ...@@ -9,6 +9,9 @@ import android.app.Activity;
import android.graphics.Point; import android.graphics.Point;
import android.os.StrictMode; import android.os.StrictMode;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View; import android.view.View;
import android.widget.FrameLayout; import android.widget.FrameLayout;
...@@ -37,7 +40,7 @@ import org.chromium.ui.display.VirtualDisplayAndroid; ...@@ -37,7 +40,7 @@ import org.chromium.ui.display.VirtualDisplayAndroid;
* This view extends from GvrLayout which wraps a GLSurfaceView that renders VR shell. * This view extends from GvrLayout which wraps a GLSurfaceView that renders VR shell.
*/ */
@JNINamespace("vr_shell") @JNINamespace("vr_shell")
public class VrShellImpl extends GvrLayout implements VrShell { public class VrShellImpl extends GvrLayout implements VrShell, SurfaceHolder.Callback {
private static final String TAG = "VrShellImpl"; private static final String TAG = "VrShellImpl";
// TODO(mthiesse): These values work well for Pixel/Pixel XL in VR, but we need to come up with // TODO(mthiesse): These values work well for Pixel/Pixel XL in VR, but we need to come up with
...@@ -63,7 +66,7 @@ public class VrShellImpl extends GvrLayout implements VrShell { ...@@ -63,7 +66,7 @@ public class VrShellImpl extends GvrLayout implements VrShell {
private long mNativeVrShell; private long mNativeVrShell;
private FrameLayout mUiCVCContainer; private FrameLayout mUiCVCContainer;
private FrameLayout mPresentationView; private View mPresentationView;
// The tab that holds the main ContentViewCore. // The tab that holds the main ContentViewCore.
private Tab mTab; private Tab mTab;
...@@ -77,6 +80,8 @@ public class VrShellImpl extends GvrLayout implements VrShell { ...@@ -77,6 +80,8 @@ public class VrShellImpl extends GvrLayout implements VrShell {
private ContentViewCore mUiCVC; private ContentViewCore mUiCVC;
private VrWindowAndroid mUiVrWindowAndroid; private VrWindowAndroid mUiVrWindowAndroid;
private boolean mReprojectedRendering;
public VrShellImpl(Activity activity) { public VrShellImpl(Activity activity) {
super(activity); super(activity);
mActivity = activity; mActivity = activity;
...@@ -88,12 +93,23 @@ public class VrShellImpl extends GvrLayout implements VrShell { ...@@ -88,12 +93,23 @@ public class VrShellImpl extends GvrLayout implements VrShell {
}; };
addView(mUiCVCContainer, 0, new FrameLayout.LayoutParams(0, 0)); addView(mUiCVCContainer, 0, new FrameLayout.LayoutParams(0, 0));
mReprojectedRendering = setAsyncReprojectionEnabled(true);
if (mReprojectedRendering) {
// No need render to a Surface if we're reprojected. We'll be rendering with surfaceless
// EGL.
mPresentationView = new FrameLayout(mActivity); mPresentationView = new FrameLayout(mActivity);
setPresentationView(mPresentationView);
if (setAsyncReprojectionEnabled(true)) { // Only enable sustained performance mode when Async reprojection decouples the app
// framerate from the display framerate.
AndroidCompat.setSustainedPerformanceMode(mActivity, true); AndroidCompat.setSustainedPerformanceMode(mActivity, true);
} else {
SurfaceView surfaceView = new SurfaceView(mActivity);
surfaceView.getHolder().addCallback(this);
mPresentationView = surfaceView;
} }
setPresentationView(mPresentationView);
DisplayAndroid primaryDisplay = DisplayAndroid.getNonMultiDisplay(activity); DisplayAndroid primaryDisplay = DisplayAndroid.getNonMultiDisplay(activity);
mContentVirtualDisplay = VirtualDisplayAndroid.createVirtualDisplay(); mContentVirtualDisplay = VirtualDisplayAndroid.createVirtualDisplay();
mContentVirtualDisplay.setTo(primaryDisplay); mContentVirtualDisplay.setTo(primaryDisplay);
...@@ -118,7 +134,7 @@ public class VrShellImpl extends GvrLayout implements VrShell { ...@@ -118,7 +134,7 @@ public class VrShellImpl extends GvrLayout implements VrShell {
mNativeVrShell = nativeInit(mContentCVC.getWebContents(), mNativeVrShell = nativeInit(mContentCVC.getWebContents(),
mContentVrWindowAndroid.getNativePointer(), mUiContents, mContentVrWindowAndroid.getNativePointer(), mUiContents,
mUiVrWindowAndroid.getNativePointer(), forWebVR, delegate, mUiVrWindowAndroid.getNativePointer(), forWebVR, delegate,
getGvrApi().getNativeGvrContext()); getGvrApi().getNativeGvrContext(), mReprojectedRendering);
// Set the UI and content sizes before we load the UI. // Set the UI and content sizes before we load the UI.
setUiCssSize(DEFAULT_UI_WIDTH, DEFAULT_UI_HEIGHT, DEFAULT_DPR); setUiCssSize(DEFAULT_UI_WIDTH, DEFAULT_UI_HEIGHT, DEFAULT_DPR);
...@@ -277,9 +293,28 @@ public class VrShellImpl extends GvrLayout implements VrShell { ...@@ -277,9 +293,28 @@ public class VrShellImpl extends GvrLayout implements VrShell {
getUiLayout().setCloseButtonListener(runner); getUiLayout().setCloseButtonListener(runner);
} }
@Override
public void surfaceCreated(SurfaceHolder holder) {
nativeSetSurface(mNativeVrShell, holder.getSurface());
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// No need to do anything here, we don't care about surface width/height.
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO(mthiesse): For now we don't need to handle this because we exit VR on activity pause
// (which destroys the surface). If in the future we don't destroy VR Shell on exiting,
// we will need to handle this, or at least properly handle surfaceCreated being called
// multiple times.
}
private native long nativeInit(WebContents contentWebContents, private native long nativeInit(WebContents contentWebContents,
long nativeContentWindowAndroid, WebContents uiWebContents, long nativeUiWindowAndroid, long nativeContentWindowAndroid, WebContents uiWebContents, long nativeUiWindowAndroid,
boolean forWebVR, VrShellDelegate delegate, long gvrApi); boolean forWebVR, VrShellDelegate delegate, long gvrApi, boolean reprojectedRendering);
private native void nativeSetSurface(long nativeVrShell, Surface surface);
private native void nativeLoadUIContent(long nativeVrShell); private native void nativeLoadUIContent(long nativeVrShell);
private native void nativeDestroy(long nativeVrShell); private native void nativeDestroy(long nativeVrShell);
private native void nativeOnTriggerEvent(long nativeVrShell); private native void nativeOnTriggerEvent(long nativeVrShell);
......
...@@ -72,8 +72,10 @@ if (current_cpu == "arm" || current_cpu == "arm64") { ...@@ -72,8 +72,10 @@ if (current_cpu == "arm" || current_cpu == "arm64") {
"//ui/gl/init", "//ui/gl/init",
] ]
libs = libs = [
[ "//third_party/gvr-android-sdk/libgvr_shim_static_${current_cpu}.a" ] "//third_party/gvr-android-sdk/libgvr_shim_static_${current_cpu}.a",
"android",
]
configs += [ "//third_party/gvr-android-sdk:libgvr_config" ] configs += [ "//third_party/gvr-android-sdk:libgvr_config" ]
} }
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "chrome/browser/android/vr_shell/vr_shell.h" #include "chrome/browser/android/vr_shell/vr_shell.h"
#include <android/native_window_jni.h>
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/threading/platform_thread.h" #include "base/threading/platform_thread.h"
#include "base/threading/thread.h" #include "base/threading/thread.h"
...@@ -48,14 +50,16 @@ class GLThread : public base::Thread { ...@@ -48,14 +50,16 @@ class GLThread : public base::Thread {
const base::WeakPtr<VrInputManager>& ui_input_manager, const base::WeakPtr<VrInputManager>& ui_input_manager,
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner, scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
gvr_context* gvr_api, gvr_context* gvr_api,
bool initially_web_vr) bool initially_web_vr,
bool reprojected_rendering)
: base::Thread("VrShellGL"), : base::Thread("VrShellGL"),
weak_vr_shell_(weak_vr_shell), weak_vr_shell_(weak_vr_shell),
content_input_manager_(content_input_manager), content_input_manager_(content_input_manager),
ui_input_manager_(ui_input_manager), ui_input_manager_(ui_input_manager),
main_thread_task_runner_(std::move(main_thread_task_runner)), main_thread_task_runner_(std::move(main_thread_task_runner)),
gvr_api_(gvr_api), gvr_api_(gvr_api),
initially_web_vr_(initially_web_vr) {} initially_web_vr_(initially_web_vr),
reprojected_rendering_(reprojected_rendering) {}
~GLThread() override { ~GLThread() override {
Stop(); Stop();
...@@ -70,11 +74,10 @@ class GLThread : public base::Thread { ...@@ -70,11 +74,10 @@ class GLThread : public base::Thread {
std::move(ui_input_manager_), std::move(ui_input_manager_),
std::move(main_thread_task_runner_), std::move(main_thread_task_runner_),
gvr_api_, gvr_api_,
initially_web_vr_)); initially_web_vr_,
reprojected_rendering_));
weak_vr_shell_gl_ = vr_shell_gl_->GetWeakPtr(); weak_vr_shell_gl_ = vr_shell_gl_->GetWeakPtr();
if (!vr_shell_gl_->Initialize()) { vr_shell_gl_->Initialize();
vr_shell_gl_.reset();
}
} }
void CleanUp() override { void CleanUp() override {
vr_shell_gl_.reset(); vr_shell_gl_.reset();
...@@ -91,6 +94,7 @@ class GLThread : public base::Thread { ...@@ -91,6 +94,7 @@ class GLThread : public base::Thread {
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
gvr_context* gvr_api_; gvr_context* gvr_api_;
bool initially_web_vr_; bool initially_web_vr_;
bool reprojected_rendering_;
}; };
} // namespace } // namespace
...@@ -103,7 +107,8 @@ VrShell::VrShell(JNIEnv* env, ...@@ -103,7 +107,8 @@ VrShell::VrShell(JNIEnv* env,
ui::WindowAndroid* ui_window, ui::WindowAndroid* ui_window,
bool for_web_vr, bool for_web_vr,
VrShellDelegate* delegate, VrShellDelegate* delegate,
gvr_context* gvr_api) gvr_context* gvr_api,
bool reprojected_rendering)
: WebContentsObserver(ui_contents), : WebContentsObserver(ui_contents),
main_contents_(main_contents), main_contents_(main_contents),
content_compositor_(new VrCompositor(content_window, false)), content_compositor_(new VrCompositor(content_window, false)),
...@@ -112,6 +117,7 @@ VrShell::VrShell(JNIEnv* env, ...@@ -112,6 +117,7 @@ VrShell::VrShell(JNIEnv* env,
delegate_(delegate), delegate_(delegate),
metrics_helper_(new VrMetricsHelper(main_contents_)), metrics_helper_(new VrMetricsHelper(main_contents_)),
main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
reprojected_rendering_(reprojected_rendering),
weak_ptr_factory_(this) { weak_ptr_factory_(this) {
DCHECK(g_instance == nullptr); DCHECK(g_instance == nullptr);
g_instance = this; g_instance = this;
...@@ -128,7 +134,8 @@ VrShell::VrShell(JNIEnv* env, ...@@ -128,7 +134,8 @@ VrShell::VrShell(JNIEnv* env,
ui_input_manager_->GetWeakPtr(), ui_input_manager_->GetWeakPtr(),
main_thread_task_runner_, main_thread_task_runner_,
gvr_api, gvr_api,
for_web_vr)); for_web_vr,
reprojected_rendering_));
base::Thread::Options options(base::MessageLoop::TYPE_DEFAULT, 0); base::Thread::Options options(base::MessageLoop::TYPE_DEFAULT, 0);
options.priority = base::ThreadPriority::DISPLAY; options.priority = base::ThreadPriority::DISPLAY;
...@@ -215,6 +222,18 @@ void VrShell::OnResume(JNIEnv* env, const JavaParamRef<jobject>& obj) { ...@@ -215,6 +222,18 @@ void VrShell::OnResume(JNIEnv* env, const JavaParamRef<jobject>& obj) {
SetShowingOverscrollGlow(false); SetShowingOverscrollGlow(false);
} }
void VrShell::SetSurface(JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& surface) {
CHECK(!reprojected_rendering_);
GLThread* thread = static_cast<GLThread*>(gl_thread_.get());
gfx::AcceleratedWidget window =
ANativeWindow_fromSurface(base::android::AttachCurrentThread(), surface);
PostToGlThreadWhenReady(base::Bind(&VrShellGl::InitializeGl,
thread->GetVrShellGl(),
base::Unretained(window)));
}
void VrShell::SetShowingOverscrollGlow(bool showing_glow) { void VrShell::SetShowingOverscrollGlow(bool showing_glow) {
main_contents_->GetRenderWidgetHostView()->SetShowingOverscrollGlow( main_contents_->GetRenderWidgetHostView()->SetShowingOverscrollGlow(
showing_glow); showing_glow);
...@@ -453,14 +472,14 @@ jlong Init(JNIEnv* env, const JavaParamRef<jobject>& obj, ...@@ -453,14 +472,14 @@ jlong Init(JNIEnv* env, const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& ui_web_contents, const JavaParamRef<jobject>& ui_web_contents,
jlong ui_window_android, jboolean for_web_vr, jlong ui_window_android, jboolean for_web_vr,
const base::android::JavaParamRef<jobject>& delegate, const base::android::JavaParamRef<jobject>& delegate,
jlong gvr_api) { jlong gvr_api, jboolean reprojected_rendering) {
return reinterpret_cast<intptr_t>(new VrShell( return reinterpret_cast<intptr_t>(new VrShell(
env, obj, content::WebContents::FromJavaWebContents(content_web_contents), env, obj, content::WebContents::FromJavaWebContents(content_web_contents),
reinterpret_cast<ui::WindowAndroid*>(content_window_android), reinterpret_cast<ui::WindowAndroid*>(content_window_android),
content::WebContents::FromJavaWebContents(ui_web_contents), content::WebContents::FromJavaWebContents(ui_web_contents),
reinterpret_cast<ui::WindowAndroid*>(ui_window_android), reinterpret_cast<ui::WindowAndroid*>(ui_window_android),
for_web_vr, VrShellDelegate::GetNativeDelegate(env, delegate), for_web_vr, VrShellDelegate::GetNativeDelegate(env, delegate),
reinterpret_cast<gvr_context*>(gvr_api))); reinterpret_cast<gvr_context*>(gvr_api), reprojected_rendering));
} }
} // namespace vr_shell } // namespace vr_shell
...@@ -63,7 +63,8 @@ class VrShell : public device::GvrDelegate, content::WebContentsObserver { ...@@ -63,7 +63,8 @@ class VrShell : public device::GvrDelegate, content::WebContentsObserver {
ui::WindowAndroid* ui_window, ui::WindowAndroid* ui_window,
bool for_web_vr, bool for_web_vr,
VrShellDelegate* delegate, VrShellDelegate* delegate,
gvr_context* gvr_api); gvr_context* gvr_api,
bool reprojected_rendering);
void LoadUIContent(JNIEnv* env, void LoadUIContent(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj); const base::android::JavaParamRef<jobject>& obj);
...@@ -74,6 +75,9 @@ class VrShell : public device::GvrDelegate, content::WebContentsObserver { ...@@ -74,6 +75,9 @@ class VrShell : public device::GvrDelegate, content::WebContentsObserver {
const base::android::JavaParamRef<jobject>& obj); const base::android::JavaParamRef<jobject>& obj);
void OnResume(JNIEnv* env, void OnResume(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj); const base::android::JavaParamRef<jobject>& obj);
void SetSurface(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
const base::android::JavaParamRef<jobject>& surface);
void SetWebVrMode(JNIEnv* env, void SetWebVrMode(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jobject>& obj,
bool enabled); bool enabled);
...@@ -158,6 +162,7 @@ class VrShell : public device::GvrDelegate, content::WebContentsObserver { ...@@ -158,6 +162,7 @@ class VrShell : public device::GvrDelegate, content::WebContentsObserver {
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
std::unique_ptr<base::Thread> gl_thread_; std::unique_ptr<base::Thread> gl_thread_;
bool reprojected_rendering_;
base::WeakPtrFactory<VrShell> weak_ptr_factory_; base::WeakPtrFactory<VrShell> weak_ptr_factory_;
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "chrome/browser/android/vr_shell/vr_shell_gl.h" #include "chrome/browser/android/vr_shell/vr_shell_gl.h"
#include "base/android/jni_android.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
...@@ -173,6 +174,10 @@ int64_t TimeInMicroseconds() { ...@@ -173,6 +174,10 @@ int64_t TimeInMicroseconds() {
std::chrono::steady_clock::now().time_since_epoch()).count(); std::chrono::steady_clock::now().time_since_epoch()).count();
} }
void WaitForSwapAck(const base::Closure& callback, gfx::SwapResult result) {
callback.Run();
}
} // namespace } // namespace
VrShellGl::VrShellGl( VrShellGl::VrShellGl(
...@@ -181,8 +186,10 @@ VrShellGl::VrShellGl( ...@@ -181,8 +186,10 @@ VrShellGl::VrShellGl(
const base::WeakPtr<VrInputManager>& ui_input_manager, const base::WeakPtr<VrInputManager>& ui_input_manager,
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner, scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
gvr_context* gvr_api, gvr_context* gvr_api,
bool initially_web_vr) bool initially_web_vr,
bool reprojected_rendering)
: web_vr_mode_(initially_web_vr), : web_vr_mode_(initially_web_vr),
surfaceless_rendering_(reprojected_rendering),
task_runner_(base::ThreadTaskRunnerHandle::Get()), task_runner_(base::ThreadTaskRunnerHandle::Get()),
weak_vr_shell_(weak_vr_shell), weak_vr_shell_(weak_vr_shell),
content_input_manager_(content_input_manager), content_input_manager_(content_input_manager),
...@@ -196,48 +203,52 @@ VrShellGl::~VrShellGl() { ...@@ -196,48 +203,52 @@ VrShellGl::~VrShellGl() {
draw_task_.Cancel(); draw_task_.Cancel();
} }
bool VrShellGl::Initialize() { void VrShellGl::Initialize() {
if (!InitializeGl()) return false;
gvr::Mat4f identity; gvr::Mat4f identity;
SetIdentityM(identity); SetIdentityM(identity);
webvr_head_pose_.resize(kPoseRingBufferSize, identity); webvr_head_pose_.resize(kPoseRingBufferSize, identity);
webvr_head_pose_valid_.resize(kPoseRingBufferSize, false); webvr_head_pose_valid_.resize(kPoseRingBufferSize, false);
draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this)));
scene_.reset(new UiScene); scene_.reset(new UiScene);
InitializeRenderer(); if (surfaceless_rendering_) {
// If we're rendering surfaceless, we'll never get a java surface to render
ScheduleNextDrawFrame(); // into, so we can initialize GL right away.
return true; InitializeGl(nullptr);
}
} }
bool VrShellGl::InitializeGl() { void VrShellGl::InitializeGl(gfx::AcceleratedWidget window) {
CHECK(!ready_to_draw_);
if (gl::GetGLImplementation() == gl::kGLImplementationNone && if (gl::GetGLImplementation() == gl::kGLImplementationNone &&
!gl::init::InitializeGLOneOff()) { !gl::init::InitializeGLOneOff()) {
LOG(ERROR) << "gl::init::InitializeGLOneOff failed"; LOG(ERROR) << "gl::init::InitializeGLOneOff failed";
ForceExitVr(); ForceExitVr();
return false; return;
} }
if (window) {
CHECK(!surfaceless_rendering_);
surface_ = gl::init::CreateViewGLSurface(window);
} else {
CHECK(surfaceless_rendering_);
surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size()); surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size());
}
if (!surface_.get()) { if (!surface_.get()) {
LOG(ERROR) << "gl::init::CreateOffscreenGLSurface failed"; LOG(ERROR) << "gl::init::CreateOffscreenGLSurface failed";
ForceExitVr(); ForceExitVr();
return false; return;
} }
context_ = gl::init::CreateGLContext(nullptr, surface_.get(), context_ = gl::init::CreateGLContext(nullptr, surface_.get(),
gl::GLContextAttribs()); gl::GLContextAttribs());
if (!context_.get()) { if (!context_.get()) {
LOG(ERROR) << "gl::init::CreateGLContext failed"; LOG(ERROR) << "gl::init::CreateGLContext failed";
ForceExitVr(); ForceExitVr();
return false; return;
} }
if (!context_->MakeCurrent(surface_.get())) { if (!context_->MakeCurrent(surface_.get())) {
LOG(ERROR) << "gl::GLContext::MakeCurrent() failed"; LOG(ERROR) << "gl::GLContext::MakeCurrent() failed";
ForceExitVr(); ForceExitVr();
return false; return;
} }
// TODO(mthiesse): We don't appear to have a VSync provider ever here. This is // TODO(mthiesse): We don't appear to have a VSync provider ever here. This is
...@@ -273,7 +284,13 @@ bool VrShellGl::InitializeGl() { ...@@ -273,7 +284,13 @@ bool VrShellGl::InitializeGl() {
&VrShell::SurfacesChanged, weak_vr_shell_, &VrShell::SurfacesChanged, weak_vr_shell_,
content_surface_->j_surface().obj(), content_surface_->j_surface().obj(),
ui_surface_->j_surface().obj())); ui_surface_->j_surface().obj()));
return true;
InitializeRenderer();
draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this)));
ScheduleNextDrawFrame();
ready_to_draw_ = true;
} }
void VrShellGl::OnUIFrameAvailable() { void VrShellGl::OnUIFrameAvailable() {
...@@ -386,7 +403,6 @@ void VrShellGl::InitializeRenderer() { ...@@ -386,7 +403,6 @@ void VrShellGl::InitializeRenderer() {
void VrShellGl::UpdateController(const gvr::Vec3f& forward_vector) { void VrShellGl::UpdateController(const gvr::Vec3f& forward_vector) {
controller_->UpdateState(); controller_->UpdateState();
// Note that button up/down state is transient, so ButtonUpHappened only // Note that button up/down state is transient, so ButtonUpHappened only
// returns true for a single frame (and we're guaranteed not to miss it). // returns true for a single frame (and we're guaranteed not to miss it).
if (controller_->ButtonUpHappened( if (controller_->ButtonUpHappened(
...@@ -664,8 +680,19 @@ void VrShellGl::DrawFrame() { ...@@ -664,8 +680,19 @@ void VrShellGl::DrawFrame() {
frame.Unbind(); frame.Unbind();
frame.Submit(*buffer_viewport_list_, head_pose); frame.Submit(*buffer_viewport_list_, head_pose);
// No need to SwapBuffers for an offscreen surface. // No need to swap buffers for surfaceless rendering.
if (surfaceless_rendering_) {
ScheduleNextDrawFrame();
return;
}
if (surface_->SupportsAsyncSwap()) {
surface_->SwapBuffersAsync(base::Bind(&WaitForSwapAck, base::Bind(
&VrShellGl::ScheduleNextDrawFrame, weak_ptr_factory_.GetWeakPtr())));
} else {
surface_->SwapBuffers();
ScheduleNextDrawFrame(); ScheduleNextDrawFrame();
}
} }
void VrShellGl::DrawVrShell(const gvr::Mat4f& head_pose, void VrShellGl::DrawVrShell(const gvr::Mat4f& head_pose,
...@@ -897,8 +924,10 @@ void VrShellGl::OnResume() { ...@@ -897,8 +924,10 @@ void VrShellGl::OnResume() {
gvr_api_->RefreshViewerProfile(); gvr_api_->RefreshViewerProfile();
gvr_api_->ResumeTracking(); gvr_api_->ResumeTracking();
controller_->OnResume(); controller_->OnResume();
if (ready_to_draw_) {
draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this))); draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this)));
ScheduleNextDrawFrame(); ScheduleNextDrawFrame();
}
} }
void VrShellGl::SetWebVrMode(bool enabled) { void VrShellGl::SetWebVrMode(bool enabled) {
......
...@@ -57,10 +57,12 @@ class VrShellGl { ...@@ -57,10 +57,12 @@ class VrShellGl {
const base::WeakPtr<VrInputManager>& ui_input_manager, const base::WeakPtr<VrInputManager>& ui_input_manager,
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner, scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
gvr_context* gvr_api, gvr_context* gvr_api,
bool initially_web_vr); bool initially_web_vr,
bool reprojected_rendering);
~VrShellGl(); ~VrShellGl();
bool Initialize(); void Initialize();
void InitializeGl(gfx::AcceleratedWidget window);
void DrawFrame(); void DrawFrame();
...@@ -84,7 +86,6 @@ class VrShellGl { ...@@ -84,7 +86,6 @@ class VrShellGl {
void UpdateScene(std::unique_ptr<base::ListValue> commands); void UpdateScene(std::unique_ptr<base::ListValue> commands);
private: private:
bool InitializeGl();
void GvrInit(gvr_context* gvr_api); void GvrInit(gvr_context* gvr_api);
void InitializeRenderer(); void InitializeRenderer();
void DrawVrShell(const gvr::Mat4f& head_pose, gvr::Frame &frame); void DrawVrShell(const gvr::Mat4f& head_pose, gvr::Frame &frame);
...@@ -163,6 +164,8 @@ class VrShellGl { ...@@ -163,6 +164,8 @@ class VrShellGl {
std::vector<bool> webvr_head_pose_valid_; std::vector<bool> webvr_head_pose_valid_;
int webvr_texture_id_ = 0; int webvr_texture_id_ = 0;
bool web_vr_mode_; bool web_vr_mode_;
bool ready_to_draw_ = false;
bool surfaceless_rendering_;
std::unique_ptr<VrController> controller_; std::unique_ptr<VrController> controller_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment