blob: 5f777e36f14a5b3e00f705dcb1b995568a86eadb [file] [log] [blame]
#include <jni.h>
#include <log/log.h>
#include <future>
#include "render_thread.h"
#include "shell_view.h"
namespace android {
namespace dvr {
RenderThread::RenderThread(JNIEnv* env, jobject class_loader,
jobject android_context)
: jvm_(nullptr),
class_loader_global_ref_(0),
android_context_global_ref_(0),
quit_(false) {
env->GetJavaVM(&jvm_);
// Create global references so we can access these objects on the render
// thread
class_loader_global_ref_ = env->NewGlobalRef(class_loader);
android_context_global_ref_ = env->NewGlobalRef(android_context);
std::promise<int> render_thread_init_result_promise;
thread_ = std::thread([this, &render_thread_init_result_promise] {
JNIEnv* render_thread_jni_env = nullptr;
jvm_->AttachCurrentThread(&render_thread_jni_env, nullptr);
RunRenderLoop(&render_thread_init_result_promise);
jvm_->DetachCurrentThread();
});
// Wait to see if the render thread started successfully. If not bail.
int render_thread_init_result =
render_thread_init_result_promise.get_future().get();
LOG_ALWAYS_FATAL_IF(render_thread_init_result != 0,
"Failed initializing render thread. result=%d",
render_thread_init_result);
}
RenderThread::~RenderThread() { Quit(); }
void RenderThread::Quit() {
if (thread_.joinable()) {
quit_ = true;
thread_.join();
}
JNIEnv* env = GetJniEnv();
if (class_loader_global_ref_ != 0) {
env->DeleteGlobalRef(class_loader_global_ref_);
class_loader_global_ref_ = 0;
}
if (android_context_global_ref_ != 0) {
env->DeleteGlobalRef(android_context_global_ref_);
android_context_global_ref_ = 0;
}
}
void RenderThread::EnableDebug(bool debug) { shell_view_.EnableDebug(debug); }
void RenderThread::VrMode(bool mode) { shell_view_.VrMode(mode); }
JNIEnv* RenderThread::GetJniEnv() {
JNIEnv* env;
jvm_->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
return env;
}
void RenderThread::RunRenderLoop(
std::promise<int>* init_result_promise) {
// TODO(steventhomas): Create local refs to work around b/33251144. Remove
// once that bug is fixed.
JNIEnv* env = GetJniEnv();
jobject class_loader = env->NewLocalRef(class_loader_global_ref_);
jobject android_context = env->NewLocalRef(android_context_global_ref_);
int init_result = shell_view_.Initialize(env, android_context, class_loader);
init_result += shell_view_.AllocateResources();
init_result_promise->set_value(init_result);
if (init_result == 0) {
while (!quit_)
shell_view_.DrawFrame();
} else {
ALOGE("Failed to initialize ShellView");
}
env->DeleteLocalRef(class_loader);
env->DeleteLocalRef(android_context);
}
} // namespace dvr
} // namespace android