Enough JNI/threading hackery to get it to run on Android! Broken readbacks make it crash alot though.
This commit is contained in:
parent
7abb8702ce
commit
bd3a681fd3
5 changed files with 52 additions and 37 deletions
|
@ -21,5 +21,5 @@ class AndroidGraphicsContext : public GraphicsContext {
|
||||||
public:
|
public:
|
||||||
// This is different than the base class function since on
|
// This is different than the base class function since on
|
||||||
// Android (EGL, Vulkan) we do have all this info on the render thread.
|
// Android (EGL, Vulkan) we do have all this info on the render thread.
|
||||||
virtual bool InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) {}
|
virtual bool InitFromRenderThread(ANativeWindow *wnd, int desiredBackbufferSizeX, int desiredBackbufferSizeY, int backbufferFormat, int androidVersion) = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -51,10 +51,6 @@
|
||||||
|
|
||||||
#include "app-android.h"
|
#include "app-android.h"
|
||||||
|
|
||||||
JNIEnv *jniEnvMain;
|
|
||||||
JNIEnv *jniEnvGraphics;
|
|
||||||
JavaVM *javaVM;
|
|
||||||
|
|
||||||
bool useCPUThread = true;
|
bool useCPUThread = true;
|
||||||
|
|
||||||
enum class EmuThreadState {
|
enum class EmuThreadState {
|
||||||
|
@ -113,6 +109,12 @@ static int backbuffer_format; // Android PixelFormat enum
|
||||||
static int desiredBackbufferSizeX;
|
static int desiredBackbufferSizeX;
|
||||||
static int desiredBackbufferSizeY;
|
static int desiredBackbufferSizeY;
|
||||||
|
|
||||||
|
// Cache the class loader so we can use it from native threads. Required for TextAndroid.
|
||||||
|
JavaVM* gJvm = nullptr;
|
||||||
|
static jobject gClassLoader;
|
||||||
|
static jmethodID gFindClassMethod;
|
||||||
|
|
||||||
|
|
||||||
static jmethodID postCommand;
|
static jmethodID postCommand;
|
||||||
static jobject nativeActivity;
|
static jobject nativeActivity;
|
||||||
static volatile bool exitRenderLoop;
|
static volatile bool exitRenderLoop;
|
||||||
|
@ -132,9 +134,44 @@ static std::map<SystemPermission, PermissionStatus> permissions;
|
||||||
|
|
||||||
AndroidGraphicsContext *graphicsContext;
|
AndroidGraphicsContext *graphicsContext;
|
||||||
|
|
||||||
static void EmuThreadFunc(JavaVM *vm) {
|
JNIEnv* getEnv() {
|
||||||
JNIEnv *env;
|
JNIEnv *env;
|
||||||
vm->AttachCurrentThread(&env, nullptr);
|
int status = gJvm->GetEnv((void**)&env, JNI_VERSION_1_6);
|
||||||
|
if(status < 0) {
|
||||||
|
status = gJvm->AttachCurrentThread(&env, NULL);
|
||||||
|
if(status < 0) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return env;
|
||||||
|
}
|
||||||
|
|
||||||
|
jclass findClass(const char* name) {
|
||||||
|
return static_cast<jclass>(getEnv()->CallObjectMethod(gClassLoader, gFindClassMethod, getEnv()->NewStringUTF(name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *pjvm, void *reserved) {
|
||||||
|
ILOG("JNI_OnLoad");
|
||||||
|
gJvm = pjvm; // cache the JavaVM pointer
|
||||||
|
auto env = getEnv();
|
||||||
|
//replace with one of your classes in the line below
|
||||||
|
auto randomClass = env->FindClass("org/ppsspp/ppsspp/NativeActivity");
|
||||||
|
jclass classClass = env->GetObjectClass(randomClass);
|
||||||
|
auto classLoaderClass = env->FindClass("java/lang/ClassLoader");
|
||||||
|
auto getClassLoaderMethod = env->GetMethodID(classClass, "getClassLoader",
|
||||||
|
"()Ljava/lang/ClassLoader;");
|
||||||
|
gClassLoader = env->NewGlobalRef(env->CallObjectMethod(randomClass, getClassLoaderMethod));
|
||||||
|
gFindClassMethod = env->GetMethodID(classLoaderClass, "findClass",
|
||||||
|
"(Ljava/lang/String;)Ljava/lang/Class;");
|
||||||
|
return JNI_VERSION_1_6;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EmuThreadFunc() {
|
||||||
|
JNIEnv *env;
|
||||||
|
gJvm->AttachCurrentThread(&env, nullptr);
|
||||||
|
|
||||||
|
setCurrentThreadName("Emu");
|
||||||
|
|
||||||
// There's no real requirement that NativeInit happen on this thread.
|
// There's no real requirement that NativeInit happen on this thread.
|
||||||
// We just call the update/render loop here.
|
// We just call the update/render loop here.
|
||||||
emuThreadState = (int)EmuThreadState::RUNNING;
|
emuThreadState = (int)EmuThreadState::RUNNING;
|
||||||
|
@ -142,14 +179,12 @@ static void EmuThreadFunc(JavaVM *vm) {
|
||||||
UpdateRunLoopAndroid(env);
|
UpdateRunLoopAndroid(env);
|
||||||
}
|
}
|
||||||
emuThreadState = (int)EmuThreadState::STOPPED;
|
emuThreadState = (int)EmuThreadState::STOPPED;
|
||||||
vm->DetachCurrentThread();
|
gJvm->DetachCurrentThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void EmuThreadStart(JNIEnv *env) {
|
static void EmuThreadStart(JNIEnv *env) {
|
||||||
emuThreadState = (int)EmuThreadState::START_REQUESTED;
|
emuThreadState = (int)EmuThreadState::START_REQUESTED;
|
||||||
JavaVM *vm;
|
emuThread = std::thread(&EmuThreadFunc);
|
||||||
env->GetJavaVM(&vm);
|
|
||||||
emuThread = std::thread(&EmuThreadFunc, vm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void EmuThreadStop() {
|
static void EmuThreadStop() {
|
||||||
|
@ -306,9 +341,6 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init
|
||||||
(JNIEnv *env, jclass, jstring jmodel, jint jdeviceType, jstring jlangRegion, jstring japkpath,
|
(JNIEnv *env, jclass, jstring jmodel, jint jdeviceType, jstring jlangRegion, jstring japkpath,
|
||||||
jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jcacheDir, jstring jshortcutParam,
|
jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jcacheDir, jstring jshortcutParam,
|
||||||
jint jAndroidVersion, jstring jboard) {
|
jint jAndroidVersion, jstring jboard) {
|
||||||
jniEnvMain = env;
|
|
||||||
env->GetJavaVM(&javaVM);
|
|
||||||
|
|
||||||
setCurrentThreadName("androidInit");
|
setCurrentThreadName("androidInit");
|
||||||
|
|
||||||
// Makes sure we get early permission grants.
|
// Makes sure we get early permission grants.
|
||||||
|
@ -472,15 +504,6 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) {
|
||||||
|
|
||||||
// JavaEGL
|
// JavaEGL
|
||||||
extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env, jobject obj) {
|
extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env, jobject obj) {
|
||||||
// Need to get the local JNI env for the graphics thread. Used later in draw_text_android.
|
|
||||||
int res = javaVM->GetEnv((void **)&jniEnvGraphics, JNI_VERSION_1_6);
|
|
||||||
if (res != JNI_OK) {
|
|
||||||
ELOG("GetEnv failed: %d", res);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!graphicsContext)
|
|
||||||
Crash();
|
|
||||||
|
|
||||||
// We should be running on the render thread here.
|
// We should be running on the render thread here.
|
||||||
std::string errorMessage;
|
std::string errorMessage;
|
||||||
if (renderer_inited) {
|
if (renderer_inited) {
|
||||||
|
@ -495,7 +518,6 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env,
|
||||||
ILOG("NativeApp.displayInit() first time");
|
ILOG("NativeApp.displayInit() first time");
|
||||||
graphicsContext->InitFromRenderThread(nullptr, 0, 0, 0, 0);
|
graphicsContext->InitFromRenderThread(nullptr, 0, 0, 0, 0);
|
||||||
graphicsContext->ThreadStart();
|
graphicsContext->ThreadStart();
|
||||||
NativeInitGraphics(graphicsContext);
|
|
||||||
renderer_inited = true;
|
renderer_inited = true;
|
||||||
}
|
}
|
||||||
NativeMessageReceived("recreateviews", "");
|
NativeMessageReceived("recreateviews", "");
|
||||||
|
@ -548,6 +570,7 @@ void UpdateRunLoopAndroid(JNIEnv *env) {
|
||||||
while (!renderer_inited) {
|
while (!renderer_inited) {
|
||||||
sleep_ms(20);
|
sleep_ms(20);
|
||||||
}
|
}
|
||||||
|
NativeInitGraphics(graphicsContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeUpdate();
|
NativeUpdate();
|
||||||
|
@ -852,12 +875,6 @@ extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(J
|
||||||
|
|
||||||
ANativeWindow *wnd = ANativeWindow_fromSurface(env, _surf);
|
ANativeWindow *wnd = ANativeWindow_fromSurface(env, _surf);
|
||||||
|
|
||||||
// Need to get the local JNI env for the graphics thread. Used later in draw_text_android.
|
|
||||||
int res = javaVM->GetEnv((void **)&jniEnvGraphics, JNI_VERSION_1_6);
|
|
||||||
if (res != JNI_OK) {
|
|
||||||
ELOG("GetEnv failed: %d", res);
|
|
||||||
}
|
|
||||||
|
|
||||||
WLOG("runEGLRenderLoop. display_xres=%d display_yres=%d", display_xres, display_yres);
|
WLOG("runEGLRenderLoop. display_xres=%d display_yres=%d", display_xres, display_yres);
|
||||||
|
|
||||||
if (wnd == nullptr) {
|
if (wnd == nullptr) {
|
||||||
|
@ -922,7 +939,6 @@ retry:
|
||||||
graphicsContext = nullptr;
|
graphicsContext = nullptr;
|
||||||
renderLoopRunning = false;
|
renderLoopRunning = false;
|
||||||
WLOG("Render loop function exited.");
|
WLOG("Render loop function exited.");
|
||||||
jniEnvGraphics = nullptr;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,7 @@
|
||||||
|
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
|
||||||
extern JNIEnv *jniEnvMain;
|
jclass findClass(const char* name);
|
||||||
extern JNIEnv *jniEnvGraphics;
|
JNIEnv* getEnv();
|
||||||
extern JavaVM *javaVM;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
|
||||||
TextDrawerAndroid::TextDrawerAndroid(Draw::DrawContext *draw) : TextDrawer(draw) {
|
TextDrawerAndroid::TextDrawerAndroid(Draw::DrawContext *draw) : TextDrawer(draw) {
|
||||||
env_ = jniEnvGraphics;
|
env_ = getEnv();
|
||||||
const char *textRendererClassName = "org/ppsspp/ppsspp/TextRenderer";
|
const char *textRendererClassName = "org/ppsspp/ppsspp/TextRenderer";
|
||||||
jclass localClass = env_->FindClass(textRendererClassName);
|
jclass localClass = findClass(textRendererClassName);
|
||||||
cls_textRenderer = reinterpret_cast<jclass>(env_->NewGlobalRef(localClass));
|
cls_textRenderer = reinterpret_cast<jclass>(env_->NewGlobalRef(localClass));
|
||||||
ILOG("cls_textRender: %p", cls_textRenderer);
|
ILOG("cls_textRender: %p", cls_textRenderer);
|
||||||
if (cls_textRenderer) {
|
if (cls_textRenderer) {
|
||||||
|
|
|
@ -87,4 +87,4 @@ bool Thin3DFormatToFormatAndType(DataFormat fmt, GLuint &internalFormat, GLuint
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue