blob: b85b14f483f694a4118f4287d0840fdf2f5dfca8 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/android/vr_shell/vr_shell_delegate.h"
#include <utility>
#include "base/android/jni_android.h"
#include "chrome/browser/android/vr_shell/non_presenting_gvr_delegate.h"
#include "device/vr/android/gvr/gvr_device.h"
#include "device/vr/android/gvr/gvr_device_provider.h"
#include "device/vr/android/gvr/gvr_gamepad_data_fetcher.h"
#include "jni/VrShellDelegate_jni.h"
using base::android::JavaParamRef;
using base::android::AttachCurrentThread;
namespace vr_shell {
VrShellDelegate::VrShellDelegate(JNIEnv* env, jobject obj)
: weak_ptr_factory_(this) {
j_vr_shell_delegate_.Reset(env, obj);
GvrDelegateProvider::SetInstance(this);
}
VrShellDelegate::~VrShellDelegate() {
GvrDelegateProvider::SetInstance(nullptr);
if (device_provider_) {
device_provider_->Device()->OnDelegateChanged();
}
}
VrShellDelegate* VrShellDelegate::GetNativeVrShellDelegate(
JNIEnv* env, jobject jdelegate) {
return reinterpret_cast<VrShellDelegate*>(
Java_VrShellDelegate_getNativePointer(env, jdelegate));
}
void VrShellDelegate::SetDelegate(device::GvrDelegate* delegate,
gvr_context* context) {
context_ = context;
delegate_ = delegate;
// Clean up the non-presenting delegate.
if (non_presenting_delegate_) {
device::mojom::VRVSyncProviderRequest request =
non_presenting_delegate_->OnSwitchToPresentingDelegate();
if (request.is_pending())
delegate->OnVRVsyncProviderRequest(std::move(request));
non_presenting_delegate_ = nullptr;
JNIEnv* env = AttachCurrentThread();
Java_VrShellDelegate_shutdownNonPresentingNativeContext(
env, j_vr_shell_delegate_.obj());
}
if (device_provider_) {
device::GvrDevice* device = device_provider_->Device();
device::GamepadDataFetcherManager::GetInstance()->AddFactory(
new device::GvrGamepadDataFetcher::Factory(context, device->id()));
device->OnDelegateChanged();
}
delegate_->UpdateVSyncInterval(timebase_nanos_, interval_seconds_);
}
void VrShellDelegate::RemoveDelegate() {
delegate_ = nullptr;
device::GamepadDataFetcherManager::GetInstance()->RemoveSourceFactory(
device::GAMEPAD_SOURCE_GVR);
if (device_provider_) {
CreateNonPresentingDelegate();
device_provider_->Device()->OnDelegateChanged();
}
}
void VrShellDelegate::SetPresentResult(JNIEnv* env,
const JavaParamRef<jobject>& obj,
jboolean result) {
CHECK(!present_callback_.is_null());
present_callback_.Run(result);
present_callback_.Reset();
}
void VrShellDelegate::DisplayActivate(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
if (device_provider_) {
device_provider_->Device()->OnActivate(
device::mojom::VRDisplayEventReason::MOUNTED);
}
}
void VrShellDelegate::UpdateVSyncInterval(JNIEnv* env,
const JavaParamRef<jobject>& obj,
jlong timebase_nanos,
jdouble interval_seconds) {
timebase_nanos_ = timebase_nanos;
interval_seconds_ = interval_seconds;
if (delegate_) {
delegate_->UpdateVSyncInterval(timebase_nanos_,
interval_seconds_);
}
if (non_presenting_delegate_) {
non_presenting_delegate_->UpdateVSyncInterval(timebase_nanos_,
interval_seconds_);
}
}
void VrShellDelegate::OnPause(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
if (non_presenting_delegate_) {
non_presenting_delegate_->Pause();
}
}
void VrShellDelegate::OnResume(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
if (non_presenting_delegate_) {
non_presenting_delegate_->Resume();
}
}
void VrShellDelegate::SetDeviceProvider(
device::GvrDeviceProvider* device_provider) {
CHECK(!device_provider_);
device_provider_ = device_provider;
if (!delegate_)
CreateNonPresentingDelegate();
device_provider_->Device()->OnDelegateChanged();
}
void VrShellDelegate::ClearDeviceProvider() {
non_presenting_delegate_ = nullptr;
JNIEnv* env = AttachCurrentThread();
Java_VrShellDelegate_shutdownNonPresentingNativeContext(
env, j_vr_shell_delegate_.obj());
device_provider_->Device()->OnDelegateChanged();
device_provider_ = nullptr;
}
void VrShellDelegate::RequestWebVRPresent(
const base::Callback<void(bool)>& callback) {
if (!present_callback_.is_null()) {
// Can only handle one request at a time. This is also extremely unlikely to
// happen in practice.
callback.Run(false);
return;
}
present_callback_ = std::move(callback);
// If/When VRShell is ready for use it will call SetPresentResult.
JNIEnv* env = AttachCurrentThread();
Java_VrShellDelegate_presentRequested(env, j_vr_shell_delegate_.obj());
}
void VrShellDelegate::ExitWebVRPresent() {
// VRShell is no longer needed by WebVR, allow it to shut down if it's not
// being used elsewhere.
JNIEnv* env = AttachCurrentThread();
Java_VrShellDelegate_exitWebVR(env, j_vr_shell_delegate_.obj());
}
base::WeakPtr<VrShellDelegate> VrShellDelegate::GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
void VrShellDelegate::OnVRVsyncProviderRequest(
device::mojom::VRVSyncProviderRequest request) {
GetDelegate()->OnVRVsyncProviderRequest(std::move(request));
}
void VrShellDelegate::CreateNonPresentingDelegate() {
JNIEnv* env = AttachCurrentThread();
gvr_context* context = reinterpret_cast<gvr_context*>(
Java_VrShellDelegate_createNonPresentingNativeContext(
env, j_vr_shell_delegate_.obj()));
if (!context)
return;
context_ = context;
non_presenting_delegate_ =
base::MakeUnique<NonPresentingGvrDelegate>(context);
non_presenting_delegate_->UpdateVSyncInterval(timebase_nanos_,
interval_seconds_);
}
device::GvrDelegate* VrShellDelegate::GetDelegate() {
if (delegate_)
return delegate_;
return non_presenting_delegate_.get();
}
void VrShellDelegate::SetListeningForActivate(bool listening) {
JNIEnv* env = AttachCurrentThread();
Java_VrShellDelegate_setListeningForWebVrActivate(
env, j_vr_shell_delegate_.obj(), listening);
}
// ----------------------------------------------------------------------------
// Native JNI methods
// ----------------------------------------------------------------------------
bool RegisterVrShellDelegate(JNIEnv* env) {
return RegisterNativesImpl(env);
}
jlong Init(JNIEnv* env, const JavaParamRef<jobject>& obj) {
return reinterpret_cast<intptr_t>(new VrShellDelegate(env, obj));
}
} // namespace vr_shell