blob: 5f777e36f14a5b3e00f705dcb1b995568a86eadb [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#include <jni.h>
Alex Vakulenko4fe60582017-02-02 11:35:59 -08002#include <log/log.h>
3#include <future>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08004
5#include "render_thread.h"
6#include "shell_view.h"
7
8namespace android {
9namespace dvr {
10
11RenderThread::RenderThread(JNIEnv* env, jobject class_loader,
12 jobject android_context)
13 : jvm_(nullptr),
14 class_loader_global_ref_(0),
15 android_context_global_ref_(0),
16 quit_(false) {
17 env->GetJavaVM(&jvm_);
18
19 // Create global references so we can access these objects on the render
20 // thread
21 class_loader_global_ref_ = env->NewGlobalRef(class_loader);
22 android_context_global_ref_ = env->NewGlobalRef(android_context);
23
24 std::promise<int> render_thread_init_result_promise;
25 thread_ = std::thread([this, &render_thread_init_result_promise] {
26 JNIEnv* render_thread_jni_env = nullptr;
27 jvm_->AttachCurrentThread(&render_thread_jni_env, nullptr);
28 RunRenderLoop(&render_thread_init_result_promise);
29 jvm_->DetachCurrentThread();
30 });
31
32 // Wait to see if the render thread started successfully. If not bail.
33 int render_thread_init_result =
34 render_thread_init_result_promise.get_future().get();
35 LOG_ALWAYS_FATAL_IF(render_thread_init_result != 0,
36 "Failed initializing render thread. result=%d",
37 render_thread_init_result);
38}
39
40RenderThread::~RenderThread() { Quit(); }
41
42void RenderThread::Quit() {
43 if (thread_.joinable()) {
44 quit_ = true;
45 thread_.join();
46 }
47
48 JNIEnv* env = GetJniEnv();
49 if (class_loader_global_ref_ != 0) {
50 env->DeleteGlobalRef(class_loader_global_ref_);
51 class_loader_global_ref_ = 0;
52 }
53 if (android_context_global_ref_ != 0) {
54 env->DeleteGlobalRef(android_context_global_ref_);
55 android_context_global_ref_ = 0;
56 }
57}
58
59void RenderThread::EnableDebug(bool debug) { shell_view_.EnableDebug(debug); }
60
61void RenderThread::VrMode(bool mode) { shell_view_.VrMode(mode); }
62
63JNIEnv* RenderThread::GetJniEnv() {
64 JNIEnv* env;
65 jvm_->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
66 return env;
67}
68
69void RenderThread::RunRenderLoop(
70 std::promise<int>* init_result_promise) {
71 // TODO(steventhomas): Create local refs to work around b/33251144. Remove
72 // once that bug is fixed.
73 JNIEnv* env = GetJniEnv();
74 jobject class_loader = env->NewLocalRef(class_loader_global_ref_);
75 jobject android_context = env->NewLocalRef(android_context_global_ref_);
76
77 int init_result = shell_view_.Initialize(env, android_context, class_loader);
78 init_result += shell_view_.AllocateResources();
79 init_result_promise->set_value(init_result);
80 if (init_result == 0) {
81 while (!quit_)
82 shell_view_.DrawFrame();
83 } else {
84 ALOGE("Failed to initialize ShellView");
85 }
86
87 env->DeleteLocalRef(class_loader);
88 env->DeleteLocalRef(android_context);
89}
90
91} // namespace dvr
92} // namespace android