blob: 21061f96ecc56b98a8f091cc1765bd7b1afa06b6 [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 "device/vr/android/gvr/gvr_device_provider.h"
#include <jni.h>
#include "base/android/context_utils.h"
#include "base/android/jni_android.h"
#include "base/android/jni_utils.h"
#include "base/android/scoped_java_ref.h"
#include "device/vr/android/gvr/gvr_delegate.h"
#include "device/vr/android/gvr/gvr_device.h"
#include "device/vr/vr_device_manager.h"
#include "jni/GvrDeviceProvider_jni.h"
#include "third_party/gvr-android-sdk/src/ndk-beta/include/vr/gvr/capi/include/gvr.h"
using base::android::AttachCurrentThread;
using base::android::GetApplicationContext;
namespace device {
// A temporary delegate till a VrShell instance becomes available.
class GvrNonPresentingDelegate : public GvrDelegate {
public:
GvrNonPresentingDelegate() { Initialize(); }
virtual ~GvrNonPresentingDelegate() { Shutdown(); }
void Initialize() {
if (j_device_.is_null()) {
JNIEnv* env = AttachCurrentThread();
j_device_.Reset(
Java_GvrDeviceProvider_create(env, GetApplicationContext()));
jlong context =
Java_GvrDeviceProvider_getNativeContext(env, j_device_.obj());
if (!context)
return;
gvr_api_ =
gvr::GvrApi::WrapNonOwned(reinterpret_cast<gvr_context*>(context));
}
}
void Shutdown() {
if (!j_device_.is_null()) {
gvr_api_ = nullptr;
JNIEnv* env = AttachCurrentThread();
Java_GvrDeviceProvider_shutdown(env, j_device_.obj());
j_device_ = nullptr;
}
}
// GvrDelegate implementation
void SubmitWebVRFrame() override {}
void UpdateWebVRTextureBounds(int eye,
float left,
float top,
float width,
float height) override {}
gvr::GvrApi* gvr_api() override { return gvr_api_.get(); }
private:
base::android::ScopedJavaGlobalRef<jobject> j_device_;
std::unique_ptr<gvr::GvrApi> gvr_api_;
};
GvrDeviceProvider::GvrDeviceProvider()
: VRDeviceProvider(),
main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
GvrDeviceProvider::~GvrDeviceProvider() {
ExitPresent();
}
void GvrDeviceProvider::GetDevices(std::vector<VRDevice*>* devices) {
Initialize();
if (vr_device_)
devices->push_back(vr_device_.get());
}
void GvrDeviceProvider::SetClient(VRClientDispatcher* client) {
if (!client_)
client_.reset(client);
}
void GvrDeviceProvider::Initialize() {
if (!non_presenting_delegate_) {
non_presenting_delegate_.reset(new GvrNonPresentingDelegate());
if (non_presenting_delegate_->gvr_api()) {
vr_device_.reset(new GvrDevice(this, non_presenting_delegate_.get()));
client_->OnDeviceConnectionStatusChanged(vr_device_.get(), true);
}
}
}
bool GvrDeviceProvider::RequestPresent() {
GvrDelegateProvider* delegate_provider = GvrDelegateProvider::GetInstance();
if (!delegate_provider)
return false;
return delegate_provider->RequestWebVRPresent(this);
}
void GvrDeviceProvider::ExitPresent() {
DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
if (!vr_device_)
return;
vr_device_->SetDelegate(non_presenting_delegate_.get());
GvrDelegateProvider* delegate_provider = GvrDelegateProvider::GetInstance();
if (delegate_provider)
delegate_provider->ExitWebVRPresent();
if (client_)
client_->OnPresentEnded(vr_device_.get());
}
void GvrDeviceProvider::OnGvrDelegateReady(GvrDelegate* delegate) {
main_thread_task_runner_->PostTask(
FROM_HERE,
base::Bind(&GvrDeviceProvider::GvrDelegateReady, base::Unretained(this),
base::Unretained(delegate)));
}
void GvrDeviceProvider::OnGvrDelegateRemoved() {
if (!vr_device_)
return;
main_thread_task_runner_->PostTask(
FROM_HERE,
base::Bind(&GvrDeviceProvider::ExitPresent, base::Unretained(this)));
}
void GvrDeviceProvider::GvrDelegateReady(GvrDelegate* delegate) {
DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
vr_device_->SetDelegate(delegate);
}
} // namespace device