android_multiviewwer/app/src/main/cpp/native_renderer.cpp

114 lines
3.2 KiB
C++
Raw Normal View History

2025-08-27 15:09:05 +09:00
#include <jni.h>
2025-08-26 13:32:53 +09:00
#include <android/native_window.h>
2025-08-26 18:24:06 +09:00
#include <android/native_window_jni.h>
2025-08-26 13:32:53 +09:00
#include <android/log.h>
2025-08-26 18:24:06 +09:00
#include <thread>
2025-08-27 15:09:05 +09:00
#include "Renderer.h"
#include "Preloader.h"
2025-08-26 18:24:06 +09:00
2025-08-26 13:32:53 +09:00
#define LOG_TAG "NativeRenderer"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
2025-08-27 15:09:05 +09:00
// 전역 변수
Renderer* renderer = nullptr;
Preloader* preloader = nullptr;
JavaVM* g_vm = nullptr;
jobject g_callback_obj = nullptr;
jmethodID g_callback_method_id = nullptr;
2025-08-26 18:24:06 +09:00
2025-08-27 15:09:05 +09:00
// JNI_OnLoad 함수
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
g_vm = vm;
return JNI_VERSION_1_6;
2025-08-26 18:24:06 +09:00
}
2025-08-27 15:09:05 +09:00
void callNextMediaCallback() {
JNIEnv* env;
bool isAttached = false;
// 현재 스레드가 JVM에 연결되어 있지 않다면 연결
if (g_vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) {
g_vm->AttachCurrentThread(&env, nullptr);
isAttached = true;
2025-08-26 18:24:06 +09:00
}
2025-08-27 15:09:05 +09:00
if (g_callback_obj && g_callback_method_id) {
env->CallVoidMethod(g_callback_obj, g_callback_method_id);
2025-08-26 18:24:06 +09:00
}
2025-08-27 15:09:05 +09:00
// 이전에 연결되지 않았다면 연결 해제
if (isAttached) {
g_vm->DetachCurrentThread();
2025-08-26 18:24:06 +09:00
}
}
2025-08-27 15:09:05 +09:00
extern "C" {
2025-08-26 18:24:06 +09:00
2025-08-27 15:09:05 +09:00
JNIEXPORT jboolean JNICALL
Java_bums_lunatic_launcher_wall_NativeRenderer_nativeInit(JNIEnv* env, jobject) {
if (!renderer) {
renderer = new Renderer();
2025-08-26 18:24:06 +09:00
}
2025-08-27 15:09:05 +09:00
if (!preloader) {
preloader = new Preloader();
2025-08-26 18:24:06 +09:00
}
2025-08-27 15:09:05 +09:00
LOGI("Native renderer and preloader initialized.");
return JNI_TRUE;
2025-08-26 18:24:06 +09:00
}
2025-08-27 15:09:05 +09:00
JNIEXPORT void JNICALL
Java_bums_lunatic_launcher_wall_NativeRenderer_nativeRender(JNIEnv* env, jobject, jobject surface) {
if (!renderer || !surface) return;
2025-08-26 18:24:06 +09:00
2025-08-27 15:09:05 +09:00
ANativeWindow* window = ANativeWindow_fromSurface(env, surface);
if (!window) {
LOGE("Could not get ANativeWindow from Surface.");
2025-08-26 13:32:53 +09:00
return;
}
2025-08-27 15:09:05 +09:00
renderer->renderFrame(window);
2025-08-26 13:32:53 +09:00
2025-08-27 15:09:05 +09:00
ANativeWindow_release(window);
2025-08-26 18:24:06 +09:00
}
2025-08-26 13:32:53 +09:00
2025-08-26 18:24:06 +09:00
JNIEXPORT void JNICALL
2025-08-27 15:09:05 +09:00
Java_bums_lunatic_launcher_wall_NativeRenderer_nativeDestroy(JNIEnv* env, jobject) {
if (renderer) {
delete renderer;
renderer = nullptr;
2025-08-26 18:24:06 +09:00
}
2025-08-27 15:09:05 +09:00
if (preloader) {
delete preloader;
preloader = nullptr;
2025-08-26 18:24:06 +09:00
}
2025-08-27 15:09:05 +09:00
if (g_callback_obj) {
env->DeleteGlobalRef(g_callback_obj);
g_callback_obj = nullptr;
}
LOGI("Native renderer destroyed and memory freed.");
2025-08-26 18:24:06 +09:00
}
JNIEXPORT void JNICALL
2025-08-27 15:09:05 +09:00
Java_bums_lunatic_launcher_wall_NativeRenderer_nativeSetCurrentMedia(JNIEnv* env, jobject, jint fd) {
if (!renderer) return;
// 경로 대신 파일 디스크립터를 전달
renderer->setNextMedia(fd);
2025-08-26 13:32:53 +09:00
}
2025-08-27 15:09:05 +09:00
JNIEXPORT void JNICALL
Java_bums_lunatic_launcher_wall_NativeRenderer_nativeStartNextPreload(JNIEnv* env, jobject, jint fd) {
if (!preloader) return;
// 경로 대신 파일 디스크립터를 전달
preloader->startNextPreload(fd);
2025-08-26 13:32:53 +09:00
}
2025-08-26 18:24:06 +09:00
JNIEXPORT void JNICALL
2025-08-27 15:09:05 +09:00
Java_bums_lunatic_launcher_wall_NativeRenderer_nativeSetNextMediaCallback(JNIEnv* env, jobject, jobject callback) {
jclass clazz = env->GetObjectClass(callback);
g_callback_method_id = env->GetMethodID(clazz, "onNextMediaRequested", "()V");
g_callback_obj = env->NewGlobalRef(callback);
2025-08-26 18:24:06 +09:00
2025-08-27 15:09:05 +09:00
if (!g_callback_method_id) {
LOGE("Could not find onNextMediaRequested method ID.");
2025-08-26 18:24:06 +09:00
}
}
2025-08-27 15:09:05 +09:00
}