mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Use EGL from native code to initialize and run OpenGL on Android.
Should be more robust, allows initializing desktop GL if available, and lets us take control of the render loop.
This commit is contained in:
parent
c2eb6a2fcb
commit
04f8bffa29
16 changed files with 379 additions and 576 deletions
|
@ -44,6 +44,9 @@ void cInterfaceEGL::DetectMode()
|
||||||
EGL_RED_SIZE, 8,
|
EGL_RED_SIZE, 8,
|
||||||
EGL_GREEN_SIZE, 8,
|
EGL_GREEN_SIZE, 8,
|
||||||
EGL_BLUE_SIZE, 8,
|
EGL_BLUE_SIZE, 8,
|
||||||
|
EGL_ALPHA_SIZE, 8,
|
||||||
|
EGL_DEPTH_SIZE, 16,
|
||||||
|
EGL_STENCIL_SIZE, 8,
|
||||||
EGL_RENDERABLE_TYPE, renderable_type,
|
EGL_RENDERABLE_TYPE, renderable_type,
|
||||||
EGL_NONE
|
EGL_NONE
|
||||||
};
|
};
|
||||||
|
@ -95,7 +98,6 @@ void cInterfaceEGL::DetectMode()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create rendering window.
|
// Create rendering window.
|
||||||
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
|
|
||||||
bool cInterfaceEGL::Create(void *window_handle, bool core)
|
bool cInterfaceEGL::Create(void *window_handle, bool core)
|
||||||
{
|
{
|
||||||
const char *s;
|
const char *s;
|
||||||
|
@ -128,6 +130,9 @@ bool cInterfaceEGL::Create(void *window_handle, bool core)
|
||||||
EGL_RED_SIZE, 8,
|
EGL_RED_SIZE, 8,
|
||||||
EGL_GREEN_SIZE, 8,
|
EGL_GREEN_SIZE, 8,
|
||||||
EGL_BLUE_SIZE, 8,
|
EGL_BLUE_SIZE, 8,
|
||||||
|
EGL_ALPHA_SIZE, 8,
|
||||||
|
EGL_DEPTH_SIZE, 16,
|
||||||
|
EGL_STENCIL_SIZE, 8,
|
||||||
EGL_NONE };
|
EGL_NONE };
|
||||||
|
|
||||||
EGLint ctx_attribs[] = {
|
EGLint ctx_attribs[] = {
|
||||||
|
@ -154,8 +159,7 @@ bool cInterfaceEGL::Create(void *window_handle, bool core)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs))
|
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
|
||||||
{
|
|
||||||
INFO_LOG(G3D, "Error: couldn't get an EGL visual config\n");
|
INFO_LOG(G3D, "Error: couldn't get an EGL visual config\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -181,15 +185,13 @@ bool cInterfaceEGL::Create(void *window_handle, bool core)
|
||||||
INFO_LOG(G3D, "EGL_CLIENT_APIS = %s\n", s);
|
INFO_LOG(G3D, "EGL_CLIENT_APIS = %s\n", s);
|
||||||
|
|
||||||
egl_ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, ctx_attribs );
|
egl_ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, ctx_attribs );
|
||||||
if (!egl_ctx)
|
if (!egl_ctx) {
|
||||||
{
|
|
||||||
INFO_LOG(G3D, "Error: eglCreateContext failed\n");
|
INFO_LOG(G3D, "Error: eglCreateContext failed\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
egl_surf = eglCreateWindowSurface(egl_dpy, config, native_window, nullptr);
|
egl_surf = eglCreateWindowSurface(egl_dpy, config, native_window, nullptr);
|
||||||
if (!egl_surf)
|
if (!egl_surf) {
|
||||||
{
|
|
||||||
INFO_LOG(G3D, "Error: eglCreateWindowSurface failed\n");
|
INFO_LOG(G3D, "Error: eglCreateWindowSurface failed\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -207,7 +209,6 @@ bool cInterfaceEGL::ClearCurrent()
|
||||||
return eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
return eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close backend
|
|
||||||
void cInterfaceEGL::Shutdown()
|
void cInterfaceEGL::Shutdown()
|
||||||
{
|
{
|
||||||
ShutdownPlatform();
|
ShutdownPlatform();
|
||||||
|
|
|
@ -20,6 +20,8 @@ protected:
|
||||||
virtual EGLDisplay OpenDisplay() = 0;
|
virtual EGLDisplay OpenDisplay() = 0;
|
||||||
virtual EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) = 0;
|
virtual EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) = 0;
|
||||||
virtual void ShutdownPlatform() = 0;
|
virtual void ShutdownPlatform() = 0;
|
||||||
|
virtual void SetInternalResolution(int internalWidth, int internalHeight) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void SwapInterval(int Interval);
|
void SwapInterval(int Interval);
|
||||||
void Swap();
|
void Swap();
|
||||||
|
|
|
@ -11,9 +11,9 @@ EGLDisplay cInterfaceEGLAndroid::OpenDisplay()
|
||||||
|
|
||||||
EGLNativeWindowType cInterfaceEGLAndroid::InitializePlatform(EGLNativeWindowType host_window, EGLConfig config)
|
EGLNativeWindowType cInterfaceEGLAndroid::InitializePlatform(EGLNativeWindowType host_window, EGLConfig config)
|
||||||
{
|
{
|
||||||
EGLint format;
|
EGLint format = 0;
|
||||||
eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &format);
|
eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &format);
|
||||||
ANativeWindow_setBuffersGeometry(host_window, 0, 0, format);
|
ANativeWindow_setBuffersGeometry(host_window, internalWidth_, internalHeight_, format);
|
||||||
|
|
||||||
const int width = ANativeWindow_getWidth(host_window);
|
const int width = ANativeWindow_getWidth(host_window);
|
||||||
const int height = ANativeWindow_getHeight(host_window);
|
const int height = ANativeWindow_getHeight(host_window);
|
||||||
|
|
|
@ -6,10 +6,19 @@
|
||||||
|
|
||||||
#include "Common/GL/GLInterface/EGL.h"
|
#include "Common/GL/GLInterface/EGL.h"
|
||||||
|
|
||||||
class cInterfaceEGLAndroid : public cInterfaceEGL
|
class cInterfaceEGLAndroid : public cInterfaceEGL {
|
||||||
{
|
public:
|
||||||
|
cInterfaceEGLAndroid() : internalWidth_(0), internalHeight_(0) {}
|
||||||
protected:
|
protected:
|
||||||
EGLDisplay OpenDisplay() override;
|
EGLDisplay OpenDisplay() override;
|
||||||
EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) override;
|
EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) override;
|
||||||
void ShutdownPlatform() override;
|
void ShutdownPlatform() override;
|
||||||
|
void SetInternalResolution(int internalWidth, int internalHeight) override {
|
||||||
|
internalWidth_ = internalWidth;
|
||||||
|
internalHeight_ = internalHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int internalWidth_;
|
||||||
|
int internalHeight_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -43,8 +43,5 @@ public:
|
||||||
virtual bool PeekMessages() { return false; }
|
virtual bool PeekMessages() { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
extern cInterfaceBase *GLInterface;
|
|
||||||
|
|
||||||
// This function has to be defined along the Host_ functions from Core/Host.h.
|
|
||||||
// Current canonical implementation: DolphinWX/GLInterface/GLInterface.cpp.
|
|
||||||
cInterfaceBase* HostGL_CreateGLInterface();
|
cInterfaceBase* HostGL_CreateGLInterface();
|
||||||
|
|
|
@ -637,6 +637,7 @@ UI::EventReturn GameSettingsScreen::OnHardwareTransform(UI::EventParams &e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
UI::EventReturn GameSettingsScreen::OnScreenRotation(UI::EventParams &e) {
|
UI::EventReturn GameSettingsScreen::OnScreenRotation(UI::EventParams &e) {
|
||||||
|
ILOG("New display rotation: %d", g_Config.iScreenRotation);
|
||||||
System_SendMessage("rotate", "");
|
System_SendMessage("rotate", "");
|
||||||
return UI::EVENT_DONE;
|
return UI::EVENT_DONE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,7 +210,8 @@ void QtHost::ShutdownSound() { }
|
||||||
std::string NativeQueryConfig(std::string query) {
|
std::string NativeQueryConfig(std::string query) {
|
||||||
char temp[128];
|
char temp[128];
|
||||||
if (query == "screenRotation") {
|
if (query == "screenRotation") {
|
||||||
sprintf(temp, "%i", g_Config.iScreenRotation);
|
ILOG("g_Config.screenRotation = %d", g_Config.iScreenRotation);
|
||||||
|
snprintf(temp, sizeof(temp), "%d", g_Config.iScreenRotation);
|
||||||
return std::string(temp);
|
return std::string(temp);
|
||||||
} else if (query == "immersiveMode") {
|
} else if (query == "immersiveMode") {
|
||||||
return std::string(g_Config.bImmersiveMode ? "1" : "0");
|
return std::string(g_Config.bImmersiveMode ? "1" : "0");
|
||||||
|
@ -224,7 +225,7 @@ std::string NativeQueryConfig(std::string query) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int max_res = std::max(System_GetPropertyInt(SYSPROP_DISPLAY_XRES), System_GetPropertyInt(SYSPROP_DISPLAY_YRES)) / 480 + 1;
|
int max_res = std::max(System_GetPropertyInt(SYSPROP_DISPLAY_XRES), System_GetPropertyInt(SYSPROP_DISPLAY_YRES)) / 480 + 1;
|
||||||
sprintf(temp, "%i", std::min(scale, max_res));
|
snprintf(temp, sizeof(temp), "%d", std::min(scale, max_res));
|
||||||
return std::string(temp);
|
return std::string(temp);
|
||||||
} else if (query == "force44khz") {
|
} else if (query == "force44khz") {
|
||||||
return std::string("0");
|
return std::string("0");
|
||||||
|
|
|
@ -99,8 +99,14 @@ ARCH_FILES := \
|
||||||
ArmEmitterTest.cpp
|
ArmEmitterTest.cpp
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
EGL_FILES := \
|
||||||
|
$(SRC)/Common/GL/GLInterface/EGL.cpp \
|
||||||
|
$(SRC)/Common/GL/GLInterface/EGLAndroid.cpp \
|
||||||
|
$(SRC)/Common/GL/GLInterface/GLInterface.cpp
|
||||||
|
|
||||||
EXEC_AND_LIB_FILES := \
|
EXEC_AND_LIB_FILES := \
|
||||||
$(ARCH_FILES) \
|
$(ARCH_FILES) \
|
||||||
|
$(EGL_FILES) \
|
||||||
TestRunner.cpp \
|
TestRunner.cpp \
|
||||||
$(SRC)/Core/MIPS/MIPS.cpp.arm \
|
$(SRC)/Core/MIPS/MIPS.cpp.arm \
|
||||||
$(SRC)/Core/MIPS/MIPSAnalyst.cpp \
|
$(SRC)/Core/MIPS/MIPSAnalyst.cpp \
|
||||||
|
|
|
@ -15,7 +15,7 @@ LOCAL_C_INCLUDES := \
|
||||||
$(LOCAL_PATH)
|
$(LOCAL_PATH)
|
||||||
|
|
||||||
LOCAL_STATIC_LIBRARIES := native libzip
|
LOCAL_STATIC_LIBRARIES := native libzip
|
||||||
LOCAL_LDLIBS := -lz -lGLESv2 -lOpenSLES -lEGL -ldl -llog
|
LOCAL_LDLIBS := -lz -landroid -lGLESv2 -lOpenSLES -lEGL -ldl -llog
|
||||||
|
|
||||||
# ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
# ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||||
ifeq ($(findstring armeabi-v7a,$(TARGET_ARCH_ABI)),armeabi-v7a)
|
ifeq ($(findstring armeabi-v7a,$(TARGET_ARCH_ABI)),armeabi-v7a)
|
||||||
|
|
|
@ -6,10 +6,12 @@
|
||||||
|
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
|
#include <android/native_window_jni.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <GLES2/gl2.h>
|
#include <GLES2/gl2.h>
|
||||||
#include <GLES2/gl2ext.h>
|
#include <GLES2/gl2ext.h>
|
||||||
|
#include <EGL/EGL.h>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "base/basictypes.h"
|
||||||
|
@ -27,6 +29,8 @@
|
||||||
#include "android/jni/native_audio.h"
|
#include "android/jni/native_audio.h"
|
||||||
#include "gfx/gl_common.h"
|
#include "gfx/gl_common.h"
|
||||||
|
|
||||||
|
#include "Common/GL/GLInterfaceBase.h"
|
||||||
|
|
||||||
#include "app-android.h"
|
#include "app-android.h"
|
||||||
|
|
||||||
static JNIEnv *jniEnvUI;
|
static JNIEnv *jniEnvUI;
|
||||||
|
@ -66,6 +70,8 @@ static int display_yres;
|
||||||
|
|
||||||
static jmethodID postCommand;
|
static jmethodID postCommand;
|
||||||
static jobject nativeActivity;
|
static jobject nativeActivity;
|
||||||
|
static volatile bool exitRenderLoop;
|
||||||
|
bool renderLoopRunning;
|
||||||
|
|
||||||
// Android implementation of callbacks to the Java part of the app
|
// Android implementation of callbacks to the Java part of the app
|
||||||
void SystemToast(const char *text) {
|
void SystemToast(const char *text) {
|
||||||
|
@ -313,18 +319,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) {
|
||||||
ILOG("NativeApp.shutdown() -- end");
|
ILOG("NativeApp.shutdown() -- end");
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env, jobject obj) {
|
extern "C" void Java_org_ppsspp_ppsspp_NativeApp_displayResize(JNIEnv *, jclass, jint w, jint h, jint dpi, jfloat refreshRate) {
|
||||||
ILOG("NativeApp.displayInit()");
|
|
||||||
if (!renderer_inited) {
|
|
||||||
NativeInitGraphics();
|
|
||||||
renderer_inited = true;
|
|
||||||
} else {
|
|
||||||
NativeDeviceLost(); // ???
|
|
||||||
ILOG("displayInit: NativeDeviceLost completed.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayResize(JNIEnv *, jobject clazz, jint w, jint h, jint dpi, jfloat refreshRate) {
|
|
||||||
ILOG("NativeApp.displayResize(%i x %i, dpi=%i, refresh=%0.2f)", w, h, dpi, refreshRate);
|
ILOG("NativeApp.displayResize(%i x %i, dpi=%i, refresh=%0.2f)", w, h, dpi, refreshRate);
|
||||||
|
|
||||||
g_dpi = dpi;
|
g_dpi = dpi;
|
||||||
|
@ -341,69 +336,8 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayResize(JNIEnv *, jo
|
||||||
NativeResized();
|
NativeResized();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayRender(JNIEnv *env, jobject obj) {
|
|
||||||
static bool hasSetThreadName = false;
|
|
||||||
if (!hasSetThreadName) {
|
|
||||||
hasSetThreadName = true;
|
|
||||||
setCurrentThreadName("AndroidRender");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (renderer_inited) {
|
|
||||||
// TODO: Look into if these locks are a perf loss
|
|
||||||
{
|
|
||||||
lock_guard guard(input_state.lock);
|
|
||||||
|
|
||||||
input_state.pad_lstick_x = left_joystick_x_async;
|
|
||||||
input_state.pad_lstick_y = left_joystick_y_async;
|
|
||||||
input_state.pad_rstick_x = right_joystick_x_async;
|
|
||||||
input_state.pad_rstick_y = right_joystick_y_async;
|
|
||||||
|
|
||||||
UpdateInputState(&input_state);
|
|
||||||
}
|
|
||||||
NativeUpdate(input_state);
|
|
||||||
|
|
||||||
{
|
|
||||||
lock_guard guard(input_state.lock);
|
|
||||||
EndInputState(&input_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
NativeRender();
|
|
||||||
time_update();
|
|
||||||
} else {
|
|
||||||
ELOG("BAD: Ended up in nativeRender even though app has quit.%s", "");
|
|
||||||
// Shouldn't really get here. Let's draw magenta.
|
|
||||||
glDepthMask(GL_TRUE);
|
|
||||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
|
||||||
glClearColor(1.0, 0.0, 1.0f, 1.0f);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
lock_guard guard(frameCommandLock);
|
|
||||||
if (!nativeActivity) {
|
|
||||||
while (!frameCommands.empty())
|
|
||||||
frameCommands.pop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while (!frameCommands.empty()) {
|
|
||||||
FrameCommand frameCmd;
|
|
||||||
frameCmd = frameCommands.front();
|
|
||||||
frameCommands.pop();
|
|
||||||
|
|
||||||
DLOG("frameCommand %s %s", frameCmd.command.c_str(), frameCmd.params.c_str());
|
|
||||||
|
|
||||||
jstring cmd = env->NewStringUTF(frameCmd.command.c_str());
|
|
||||||
jstring param = env->NewStringUTF(frameCmd.params.c_str());
|
|
||||||
env->CallVoidMethod(nativeActivity, postCommand, cmd, param);
|
|
||||||
env->DeleteLocalRef(cmd);
|
|
||||||
env->DeleteLocalRef(param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayShutdown(JNIEnv *env, jobject obj) {
|
extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayShutdown(JNIEnv *env, jobject obj) {
|
||||||
if (renderer_inited) {
|
if (renderer_inited) {
|
||||||
NativeDeviceLost();
|
|
||||||
ILOG("NativeDeviceLost completed.");
|
|
||||||
NativeShutdownGraphics();
|
|
||||||
renderer_inited = false;
|
renderer_inited = false;
|
||||||
NativeMessageReceived("recreateviews", "");
|
NativeMessageReceived("recreateviews", "");
|
||||||
}
|
}
|
||||||
|
@ -538,7 +472,7 @@ extern "C" jboolean JNICALL Java_org_ppsspp_ppsspp_NativeApp_accelerometer(JNIEn
|
||||||
return retvalX || retvalY || retvalZ;
|
return retvalX || retvalY || retvalZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void Java_org_ppsspp_ppsspp_NativeApp_sendMessage(JNIEnv *env, jclass, jstring message, jstring param) {
|
extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendMessage(JNIEnv *env, jclass, jstring message, jstring param) {
|
||||||
std::string msg = GetJavaString(env, message);
|
std::string msg = GetJavaString(env, message);
|
||||||
std::string prm = GetJavaString(env, param);
|
std::string prm = GetJavaString(env, param);
|
||||||
|
|
||||||
|
@ -547,3 +481,99 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_sendMessage(JNIEnv *env, jclass
|
||||||
}
|
}
|
||||||
NativeMessageReceived(msg.c_str(), prm.c_str());
|
NativeMessageReceived(msg.c_str(), prm.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeActivity_exitEGLRenderLoop(JNIEnv *env, jobject obj) {
|
||||||
|
if (!renderLoopRunning) {
|
||||||
|
ELOG("Render loop already exited");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
exitRenderLoop = true;
|
||||||
|
while (renderLoopRunning) {
|
||||||
|
sleep_ms(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(JNIEnv *env, jobject obj, jobject _surf) {
|
||||||
|
ANativeWindow *wnd = ANativeWindow_fromSurface(env, _surf);
|
||||||
|
|
||||||
|
WLOG("runEGLRenderLoop");
|
||||||
|
|
||||||
|
if (wnd == nullptr) {
|
||||||
|
ELOG("Error: Surface is null.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cInterfaceBase *gl = HostGL_CreateGLInterface();
|
||||||
|
if (!gl) {
|
||||||
|
ELOG("ERROR: Failed to create GL interface");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gl->SetMode(MODE_DETECT);
|
||||||
|
gl->Create(wnd);
|
||||||
|
gl->MakeCurrent();
|
||||||
|
|
||||||
|
if (!renderer_inited) {
|
||||||
|
NativeInitGraphics();
|
||||||
|
renderer_inited = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
exitRenderLoop = false;
|
||||||
|
renderLoopRunning = true;
|
||||||
|
|
||||||
|
while (!exitRenderLoop) {
|
||||||
|
static bool hasSetThreadName = false;
|
||||||
|
if (!hasSetThreadName) {
|
||||||
|
hasSetThreadName = true;
|
||||||
|
setCurrentThreadName("AndroidRender");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Look into if these locks are a perf loss
|
||||||
|
{
|
||||||
|
lock_guard guard(input_state.lock);
|
||||||
|
|
||||||
|
input_state.pad_lstick_x = left_joystick_x_async;
|
||||||
|
input_state.pad_lstick_y = left_joystick_y_async;
|
||||||
|
input_state.pad_rstick_x = right_joystick_x_async;
|
||||||
|
input_state.pad_rstick_y = right_joystick_y_async;
|
||||||
|
|
||||||
|
UpdateInputState(&input_state);
|
||||||
|
}
|
||||||
|
NativeUpdate(input_state);
|
||||||
|
|
||||||
|
{
|
||||||
|
lock_guard guard(input_state.lock);
|
||||||
|
EndInputState(&input_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeRender();
|
||||||
|
time_update();
|
||||||
|
|
||||||
|
gl->Swap();
|
||||||
|
|
||||||
|
lock_guard guard(frameCommandLock);
|
||||||
|
while (!frameCommands.empty()) {
|
||||||
|
FrameCommand frameCmd;
|
||||||
|
frameCmd = frameCommands.front();
|
||||||
|
frameCommands.pop();
|
||||||
|
|
||||||
|
WLOG("frameCommand! '%s' '%s'", frameCmd.command.c_str(), frameCmd.params.c_str());
|
||||||
|
|
||||||
|
jstring cmd = env->NewStringUTF(frameCmd.command.c_str());
|
||||||
|
jstring param = env->NewStringUTF(frameCmd.params.c_str());
|
||||||
|
env->CallVoidMethod(nativeActivity, postCommand, cmd, param);
|
||||||
|
env->DeleteLocalRef(cmd);
|
||||||
|
env->DeleteLocalRef(param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeDeviceLost();
|
||||||
|
ILOG("NativeDeviceLost completed.");
|
||||||
|
NativeShutdownGraphics();
|
||||||
|
renderer_inited = false;
|
||||||
|
|
||||||
|
delete gl;
|
||||||
|
|
||||||
|
ANativeWindow_release(wnd);
|
||||||
|
renderLoopRunning = false;
|
||||||
|
WLOG("Render loop exited;");
|
||||||
|
}
|
||||||
|
|
|
@ -37,6 +37,8 @@ import android.view.InputEvent;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.HapticFeedbackConstants;
|
import android.view.HapticFeedbackConstants;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
import android.view.Surface;
|
||||||
|
import android.view.SurfaceHolder;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnSystemUiVisibilityChangeListener;
|
import android.view.View.OnSystemUiVisibilityChangeListener;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
|
@ -46,7 +48,7 @@ import android.widget.EditText;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
public class NativeActivity extends Activity {
|
public class NativeActivity extends Activity implements SurfaceHolder.Callback {
|
||||||
// Remember to loadLibrary your JNI .so in a static {} block
|
// Remember to loadLibrary your JNI .so in a static {} block
|
||||||
|
|
||||||
// Adjust these as necessary
|
// Adjust these as necessary
|
||||||
|
@ -56,8 +58,9 @@ public class NativeActivity extends Activity {
|
||||||
private static boolean initialized = false;
|
private static boolean initialized = false;
|
||||||
|
|
||||||
// Graphics and audio interfaces
|
// Graphics and audio interfaces
|
||||||
private NativeGLView mGLSurfaceView;
|
private NativeSurfaceView mSurfaceView;
|
||||||
protected NativeRenderer nativeRenderer;
|
private Surface mSurface;
|
||||||
|
private Thread mRenderLoopThread;
|
||||||
|
|
||||||
private String shortcutParam = "";
|
private String shortcutParam = "";
|
||||||
|
|
||||||
|
@ -93,10 +96,6 @@ public class NativeActivity extends Activity {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeRenderer getRenderer() {
|
|
||||||
return nativeRenderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@TargetApi(17)
|
@TargetApi(17)
|
||||||
private void detectOptimalAudioSettings() {
|
private void detectOptimalAudioSettings() {
|
||||||
try {
|
try {
|
||||||
|
@ -223,24 +222,6 @@ public class NativeActivity extends Activity {
|
||||||
|
|
||||||
NativeApp.sendMessage("cacheDir", getCacheDir().getAbsolutePath());
|
NativeApp.sendMessage("cacheDir", getCacheDir().getAbsolutePath());
|
||||||
|
|
||||||
// OK, config should be initialized, we can query for screen rotation.
|
|
||||||
if (Build.VERSION.SDK_INT >= 9) {
|
|
||||||
updateScreenRotation();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect OpenGL support.
|
|
||||||
// We don't currently use this detection for anything but good to have in the log.
|
|
||||||
if (!detectOpenGLES20()) {
|
|
||||||
Log.i(TAG, "OpenGL ES 2.0 NOT detected. Things will likely go badly.");
|
|
||||||
} else {
|
|
||||||
if (detectOpenGLES30()) {
|
|
||||||
Log.i(TAG, "OpenGL ES 3.0 detected.");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Log.i(TAG, "OpenGL ES 2.0 detected.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vibrator = (Vibrator)getSystemService(VIBRATOR_SERVICE);
|
vibrator = (Vibrator)getSystemService(VIBRATOR_SERVICE);
|
||||||
if (Build.VERSION.SDK_INT >= 11) {
|
if (Build.VERSION.SDK_INT >= 11) {
|
||||||
checkForVibrator();
|
checkForVibrator();
|
||||||
|
@ -258,6 +239,7 @@ public class NativeActivity extends Activity {
|
||||||
Log.e(TAG, "Invalid rotation: " + rotString);
|
Log.e(TAG, "Invalid rotation: " + rotString);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Log.i(TAG, "Requested rotation: " + rot + " ('" + rotString + "')");
|
||||||
switch (rot) {
|
switch (rot) {
|
||||||
case 0:
|
case 0:
|
||||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
|
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
|
||||||
|
@ -315,6 +297,34 @@ public class NativeActivity extends Activity {
|
||||||
sz.y = 0;
|
sz.y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Runnable mEmulationRunner = new Runnable()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
// Bit of a hack - loop until onSurfaceCreated succeeds.
|
||||||
|
try {
|
||||||
|
while (mSurface == null)
|
||||||
|
{
|
||||||
|
Thread.sleep(10);
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.i(TAG, "Starting the render loop: " + mSurface);
|
||||||
|
|
||||||
|
// Start emulation using the provided Surface.
|
||||||
|
runEGLRenderLoop(mSurface);
|
||||||
|
|
||||||
|
Log.i(TAG, "Left the render loop: " + mSurface);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public native void runEGLRenderLoop(Surface surface);
|
||||||
|
// Tells the render loop thread to exit, so we can restart it.
|
||||||
|
public native void exitEGLRenderLoop();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
@ -325,6 +335,12 @@ public class NativeActivity extends Activity {
|
||||||
Initialize();
|
Initialize();
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OK, config should be initialized, we can query for screen rotation.
|
||||||
|
if (Build.VERSION.SDK_INT >= 9) {
|
||||||
|
updateScreenRotation();
|
||||||
|
}
|
||||||
|
|
||||||
// Keep the screen bright - very annoying if it goes dark when tilting away
|
// Keep the screen bright - very annoying if it goes dark when tilting away
|
||||||
Window window = this.getWindow();
|
Window window = this.getWindow();
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||||
|
@ -333,47 +349,18 @@ public class NativeActivity extends Activity {
|
||||||
gainAudioFocus(this.audioManager, this.audioFocusChangeListener);
|
gainAudioFocus(this.audioManager, this.audioFocusChangeListener);
|
||||||
NativeApp.audioInit();
|
NativeApp.audioInit();
|
||||||
|
|
||||||
mGLSurfaceView = new NativeGLView(this);
|
mSurfaceView = new NativeSurfaceView(this);
|
||||||
nativeRenderer = new NativeRenderer(this);
|
mSurfaceView.getHolder().addCallback(this);
|
||||||
|
|
||||||
Point sz = new Point();
|
Point sz = new Point();
|
||||||
getDesiredBackbufferSize(sz);
|
getDesiredBackbufferSize(sz);
|
||||||
if (sz.x > 0) {
|
if (sz.x > 0) {
|
||||||
Log.i(TAG, "Requesting fixed size buffer: " + sz.x + "x" + sz.y);
|
Log.i(TAG, "Requesting fixed size buffer: " + sz.x + "x" + sz.y);
|
||||||
// Auto-calculates new DPI and forwards to the correct call on mGLSurfaceView.getHolder()
|
// Auto-calculates new DPI and forwards to the correct call on mGLSurfaceView.getHolder()
|
||||||
nativeRenderer.setFixedSize(sz.x, sz.y, mGLSurfaceView);
|
mSurfaceView.setFixedSize(sz.x, sz.y);
|
||||||
}
|
}
|
||||||
mGLSurfaceView.setEGLContextClientVersion(2);
|
|
||||||
|
|
||||||
// Setup the GLSurface and ask android for the correct
|
setContentView(mSurfaceView);
|
||||||
// Number of bits for r, g, b, a, depth and stencil components
|
|
||||||
// The PSP only has 16-bit Z so that should be enough.
|
|
||||||
// Might want to change this for other apps (24-bit might be useful).
|
|
||||||
// Actually, we might be able to do without both stencil and depth in
|
|
||||||
// the back buffer, but that would kill non-buffered rendering.
|
|
||||||
|
|
||||||
// It appears some gingerbread devices blow up if you use a config chooser at all ???? (Xperia Play)
|
|
||||||
//if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
|
||||||
|
|
||||||
// On some (especially older devices), things blow up later (EGL_BAD_MATCH) if we don't set the format here,
|
|
||||||
// if we specify that we want destination alpha in the config chooser, which we do.
|
|
||||||
// http://grokbase.com/t/gg/android-developers/11bj40jm4w/fall-back
|
|
||||||
|
|
||||||
|
|
||||||
// Needed to avoid banding on Ouya?
|
|
||||||
if (Build.MANUFACTURER == "OUYA") {
|
|
||||||
mGLSurfaceView.getHolder().setFormat(PixelFormat.RGBX_8888);
|
|
||||||
mGLSurfaceView.setEGLConfigChooser(new NativeEGLConfigChooser());
|
|
||||||
} else {
|
|
||||||
// Many devices require that we set a config chooser, despite the documentation
|
|
||||||
// explicitly stating: "If no setEGLConfigChooser method is called, then by default the view will choose an RGB_888 surface with a depth buffer depth of at least 16 bits."
|
|
||||||
// On these devices, I get these crashes: http://stackoverflow.com/questions/14167319/android-opengl-demo-no-config-chosen
|
|
||||||
// So let's try it...
|
|
||||||
mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
mGLSurfaceView.setRenderer(nativeRenderer);
|
|
||||||
setContentView(mGLSurfaceView);
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
|
||||||
updateSystemUiVisibility();
|
updateSystemUiVisibility();
|
||||||
|
@ -381,8 +368,46 @@ public class NativeActivity extends Activity {
|
||||||
setupSystemUiCallback();
|
setupSystemUiCallback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mRenderLoopThread = new Thread(mEmulationRunner);
|
||||||
|
mRenderLoopThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void surfaceCreated(SurfaceHolder holder)
|
||||||
|
{
|
||||||
|
Log.d(TAG, "Surface created.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
|
||||||
|
{
|
||||||
|
Log.w(TAG, "Surface changed. Resolution: " + width + "x" + height);
|
||||||
|
mSurface = holder.getSurface();
|
||||||
|
if (mRenderLoopThread == null || !mRenderLoopThread.isAlive()) {
|
||||||
|
mRenderLoopThread = new Thread(mEmulationRunner);
|
||||||
|
mRenderLoopThread.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void surfaceDestroyed(SurfaceHolder holder)
|
||||||
|
{
|
||||||
|
mSurface = null;
|
||||||
|
Log.w(TAG, "Surface destroyed.");
|
||||||
|
if (mRenderLoopThread != null && mRenderLoopThread.isAlive()) {
|
||||||
|
// This will wait until the thread has exited.
|
||||||
|
exitEGLRenderLoop();
|
||||||
|
try {
|
||||||
|
mRenderLoopThread.join();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@TargetApi(19)
|
@TargetApi(19)
|
||||||
void setupSystemUiCallback() {
|
void setupSystemUiCallback() {
|
||||||
getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
|
getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
|
||||||
|
@ -397,6 +422,7 @@ public class NativeActivity extends Activity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStop() {
|
protected void onStop() {
|
||||||
|
exitEGLRenderLoop();
|
||||||
super.onStop();
|
super.onStop();
|
||||||
Log.i(TAG, "onStop - do nothing special");
|
Log.i(TAG, "onStop - do nothing special");
|
||||||
}
|
}
|
||||||
|
@ -405,11 +431,10 @@ public class NativeActivity extends Activity {
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
Log.i(TAG, "onDestroy");
|
Log.i(TAG, "onDestroy");
|
||||||
mGLSurfaceView.onDestroy();
|
mSurfaceView.onDestroy();
|
||||||
nativeRenderer.onDestroyed();
|
|
||||||
NativeApp.audioShutdown();
|
NativeApp.audioShutdown();
|
||||||
// Probably vain attempt to help the garbage collector...
|
// Probably vain attempt to help the garbage collector...
|
||||||
mGLSurfaceView = null;
|
mSurfaceView = null;
|
||||||
audioFocusChangeListener = null;
|
audioFocusChangeListener = null;
|
||||||
audioManager = null;
|
audioManager = null;
|
||||||
unregisterCallbacks();
|
unregisterCallbacks();
|
||||||
|
@ -433,7 +458,7 @@ public class NativeActivity extends Activity {
|
||||||
Log.i(TAG, "onPause");
|
Log.i(TAG, "onPause");
|
||||||
loseAudioFocus(this.audioManager, this.audioFocusChangeListener);
|
loseAudioFocus(this.audioManager, this.audioFocusChangeListener);
|
||||||
NativeApp.pause();
|
NativeApp.pause();
|
||||||
mGLSurfaceView.onPause();
|
mSurfaceView.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -448,8 +473,8 @@ public class NativeActivity extends Activity {
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i(TAG, "onResume");
|
Log.i(TAG, "onResume");
|
||||||
if (mGLSurfaceView != null) {
|
if (mSurfaceView != null) {
|
||||||
mGLSurfaceView.onResume();
|
mSurfaceView.onResume();
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "mGLSurfaceView really shouldn't be null in onResume");
|
Log.e(TAG, "mGLSurfaceView really shouldn't be null in onResume");
|
||||||
}
|
}
|
||||||
|
@ -468,7 +493,7 @@ public class NativeActivity extends Activity {
|
||||||
Point sz = new Point();
|
Point sz = new Point();
|
||||||
getDesiredBackbufferSize(sz);
|
getDesiredBackbufferSize(sz);
|
||||||
if (sz.x > 0) {
|
if (sz.x > 0) {
|
||||||
mGLSurfaceView.getHolder().setFixedSize(sz.x/2, sz.y/2);
|
mSurfaceView.getHolder().setFixedSize(sz.x/2, sz.y/2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -733,13 +758,15 @@ public class NativeActivity extends Activity {
|
||||||
.setView(fl)
|
.setView(fl)
|
||||||
.setTitle(title)
|
.setTitle(title)
|
||||||
.setPositiveButton(defaultAction, new DialogInterface.OnClickListener(){
|
.setPositiveButton(defaultAction, new DialogInterface.OnClickListener(){
|
||||||
public void onClick(DialogInterface d, int which) {
|
@Override
|
||||||
|
public void onClick(DialogInterface d, int which) {
|
||||||
NativeApp.sendMessage("inputbox_completed", input.getText().toString());
|
NativeApp.sendMessage("inputbox_completed", input.getText().toString());
|
||||||
d.dismiss();
|
d.dismiss();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){
|
.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){
|
||||||
public void onClick(DialogInterface d, int which) {
|
@Override
|
||||||
|
public void onClick(DialogInterface d, int which) {
|
||||||
NativeApp.sendMessage("inputbox_failed", "");
|
NativeApp.sendMessage("inputbox_failed", "");
|
||||||
d.cancel();
|
d.cancel();
|
||||||
}
|
}
|
||||||
|
@ -825,18 +852,18 @@ public class NativeActivity extends Activity {
|
||||||
toast.show();
|
toast.show();
|
||||||
Log.i(TAG, params);
|
Log.i(TAG, params);
|
||||||
return true;
|
return true;
|
||||||
} else if (command.equals("showKeyboard") && mGLSurfaceView != null) {
|
} else if (command.equals("showKeyboard") && mSurfaceView != null) {
|
||||||
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
// No idea what the point of the ApplicationWindowToken is or if it
|
// No idea what the point of the ApplicationWindowToken is or if it
|
||||||
// matters where we get it from...
|
// matters where we get it from...
|
||||||
inputMethodManager.toggleSoftInputFromWindow(
|
inputMethodManager.toggleSoftInputFromWindow(
|
||||||
mGLSurfaceView.getApplicationWindowToken(),
|
mSurfaceView.getApplicationWindowToken(),
|
||||||
InputMethodManager.SHOW_FORCED, 0);
|
InputMethodManager.SHOW_FORCED, 0);
|
||||||
return true;
|
return true;
|
||||||
} else if (command.equals("hideKeyboard") && mGLSurfaceView != null) {
|
} else if (command.equals("hideKeyboard") && mSurfaceView != null) {
|
||||||
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
inputMethodManager.toggleSoftInputFromWindow(
|
inputMethodManager.toggleSoftInputFromWindow(
|
||||||
mGLSurfaceView.getApplicationWindowToken(),
|
mSurfaceView.getApplicationWindowToken(),
|
||||||
InputMethodManager.SHOW_FORCED, 0);
|
InputMethodManager.SHOW_FORCED, 0);
|
||||||
return true;
|
return true;
|
||||||
} else if (command.equals("inputbox")) {
|
} else if (command.equals("inputbox")) {
|
||||||
|
@ -850,7 +877,7 @@ public class NativeActivity extends Activity {
|
||||||
Log.i(TAG, "Launching inputbox: " + title + " " + defString);
|
Log.i(TAG, "Launching inputbox: " + title + " " + defString);
|
||||||
inputBox(title, defString, "OK");
|
inputBox(title, defString, "OK");
|
||||||
return true;
|
return true;
|
||||||
} else if (command.equals("vibrate") && mGLSurfaceView != null) {
|
} else if (command.equals("vibrate") && mSurfaceView != null) {
|
||||||
int milliseconds = -1;
|
int milliseconds = -1;
|
||||||
if (params != "") {
|
if (params != "") {
|
||||||
try {
|
try {
|
||||||
|
@ -867,13 +894,13 @@ public class NativeActivity extends Activity {
|
||||||
// permission.
|
// permission.
|
||||||
switch (milliseconds) {
|
switch (milliseconds) {
|
||||||
case -1:
|
case -1:
|
||||||
mGLSurfaceView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
|
mSurfaceView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
|
||||||
break;
|
break;
|
||||||
case -2:
|
case -2:
|
||||||
mGLSurfaceView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
|
mSurfaceView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
|
||||||
break;
|
break;
|
||||||
case -3:
|
case -3:
|
||||||
mGLSurfaceView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
mSurfaceView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (vibrator != null) {
|
if (vibrator != null) {
|
||||||
|
@ -893,6 +920,7 @@ public class NativeActivity extends Activity {
|
||||||
updateSystemUiVisibility();
|
updateSystemUiVisibility();
|
||||||
}
|
}
|
||||||
} else if (command.equals("recreate")) {
|
} else if (command.equals("recreate")) {
|
||||||
|
exitEGLRenderLoop();
|
||||||
recreate();
|
recreate();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -19,6 +19,7 @@ public class NativeApp {
|
||||||
public static native void audioShutdown();
|
public static native void audioShutdown();
|
||||||
public static native void audioConfig(int optimalFramesPerBuffer, int optimalSampleRate);
|
public static native void audioConfig(int optimalFramesPerBuffer, int optimalSampleRate);
|
||||||
|
|
||||||
|
public static native void displayResize(int width, int height, int scaled_dpi, float refreshRate);
|
||||||
public static native boolean isLandscape();
|
public static native boolean isLandscape();
|
||||||
public static native boolean isAtTopLevel();
|
public static native boolean isAtTopLevel();
|
||||||
|
|
||||||
|
@ -50,4 +51,3 @@ public class NativeApp {
|
||||||
|
|
||||||
public static native String queryConfig(String queryName);
|
public static native String queryConfig(String queryName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,205 +0,0 @@
|
||||||
package org.ppsspp.ppsspp;
|
|
||||||
|
|
||||||
import javax.microedition.khronos.egl.EGL10;
|
|
||||||
import javax.microedition.khronos.egl.EGLConfig;
|
|
||||||
import javax.microedition.khronos.egl.EGLDisplay;
|
|
||||||
|
|
||||||
import android.opengl.GLSurfaceView.EGLConfigChooser;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
public class NativeEGLConfigChooser implements EGLConfigChooser {
|
|
||||||
private static final String TAG = "NativeEGLConfigChooser";
|
|
||||||
|
|
||||||
private static final int EGL_OPENGL_ES2_BIT = 4;
|
|
||||||
|
|
||||||
private class ConfigAttribs {
|
|
||||||
EGLConfig config;
|
|
||||||
public int red;
|
|
||||||
public int green;
|
|
||||||
public int blue;
|
|
||||||
public int alpha;
|
|
||||||
public int stencil;
|
|
||||||
public int depth;
|
|
||||||
public int samples;
|
|
||||||
public void Log() {
|
|
||||||
Log.i(TAG, "EGLConfig: red=" + red + " green=" + green + " blue=" + blue + " alpha=" + alpha + " depth=" + depth + " stencil=" + stencil + " samples=" + samples);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int getEglConfigAttrib(EGL10 egl, EGLDisplay display, EGLConfig config, int attr) {
|
|
||||||
int[] value = new int[1];
|
|
||||||
try {
|
|
||||||
if (egl.eglGetConfigAttrib(display, config, attr, value))
|
|
||||||
return value[0];
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
if (config == null) {
|
|
||||||
Log.e(TAG, "Called getEglConfigAttrib with null config. Bad developer.");
|
|
||||||
} else {
|
|
||||||
Log.e(TAG, "Illegal argument to getEglConfigAttrib: attr=" + attr);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigAttribs[] getConfigAttribs(EGL10 egl, EGLDisplay display, EGLConfig[] configs) {
|
|
||||||
ConfigAttribs[] attr = new ConfigAttribs[configs.length];
|
|
||||||
for (int i = 0; i < configs.length; i++) {
|
|
||||||
ConfigAttribs cfg = new ConfigAttribs();
|
|
||||||
cfg.config = configs[i];
|
|
||||||
cfg.red = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_RED_SIZE);
|
|
||||||
cfg.green = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_GREEN_SIZE);
|
|
||||||
cfg.blue = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_BLUE_SIZE);
|
|
||||||
cfg.alpha = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_ALPHA_SIZE);
|
|
||||||
cfg.depth = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_DEPTH_SIZE);
|
|
||||||
cfg.stencil = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_STENCIL_SIZE);
|
|
||||||
cfg.samples = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_SAMPLES);
|
|
||||||
attr[i] = cfg;
|
|
||||||
}
|
|
||||||
return attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
|
|
||||||
// The absolute minimum. We will do our best to choose a better config though.
|
|
||||||
int[] configSpec = {
|
|
||||||
EGL10.EGL_RED_SIZE, 5,
|
|
||||||
EGL10.EGL_GREEN_SIZE, 6,
|
|
||||||
EGL10.EGL_BLUE_SIZE, 5,
|
|
||||||
EGL10.EGL_DEPTH_SIZE, 16,
|
|
||||||
EGL10.EGL_STENCIL_SIZE, 0,
|
|
||||||
EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,
|
|
||||||
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
|
||||||
EGL10.EGL_NONE
|
|
||||||
};
|
|
||||||
|
|
||||||
int[] num_config = new int[1];
|
|
||||||
if (!egl.eglChooseConfig(display, configSpec, null, 0, num_config)) {
|
|
||||||
throw new IllegalArgumentException("eglChooseConfig failed when counting");
|
|
||||||
}
|
|
||||||
|
|
||||||
int numConfigs = num_config[0];
|
|
||||||
Log.i(TAG, "There are " + numConfigs + " egl configs");
|
|
||||||
if (numConfigs <= 0) {
|
|
||||||
throw new IllegalArgumentException("No configs match configSpec");
|
|
||||||
}
|
|
||||||
|
|
||||||
EGLConfig[] eglConfigs = new EGLConfig[numConfigs];
|
|
||||||
if (!egl.eglChooseConfig(display, configSpec, eglConfigs, numConfigs, num_config)) {
|
|
||||||
throw new IllegalArgumentException("eglChooseConfig failed when retrieving");
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigAttribs [] configs = getConfigAttribs(egl, display, eglConfigs);
|
|
||||||
|
|
||||||
ConfigAttribs chosen = null;
|
|
||||||
|
|
||||||
// Log them all.
|
|
||||||
for (int i = 0; i < configs.length; i++) {
|
|
||||||
configs[i].Log();
|
|
||||||
}
|
|
||||||
|
|
||||||
// We now ignore destination alpha as a workaround for the Mali issue
|
|
||||||
// where we get badly composited if we use it.
|
|
||||||
|
|
||||||
// First, find our ideal configuration. Prefer depth.
|
|
||||||
for (int i = 0; i < configs.length; i++) {
|
|
||||||
ConfigAttribs c = configs[i];
|
|
||||||
if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.stencil >= 8 && c.depth >= 24) {
|
|
||||||
chosen = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chosen == null) {
|
|
||||||
// Then, prefer one with 20-bit depth (Tegra 3)
|
|
||||||
for (int i = 0; i < configs.length; i++) {
|
|
||||||
ConfigAttribs c = configs[i];
|
|
||||||
if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.stencil >= 8 && c.depth >= 20) {
|
|
||||||
chosen = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chosen == null) {
|
|
||||||
// Second, accept one with 16-bit depth.
|
|
||||||
for (int i = 0; i < configs.length; i++) {
|
|
||||||
ConfigAttribs c = configs[i];
|
|
||||||
if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.stencil >= 8 && c.depth >= 16) {
|
|
||||||
chosen = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chosen == null) {
|
|
||||||
// Third, accept one with no stencil.
|
|
||||||
for (int i = 0; i < configs.length; i++) {
|
|
||||||
ConfigAttribs c = configs[i];
|
|
||||||
if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.depth >= 16) {
|
|
||||||
chosen = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chosen == null) {
|
|
||||||
// Third, accept one with alpha but with stencil, 24-bit depth.
|
|
||||||
for (int i = 0; i < configs.length; i++) {
|
|
||||||
ConfigAttribs c = configs[i];
|
|
||||||
if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 8 && c.stencil >= 8 && c.depth >= 24) {
|
|
||||||
chosen = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chosen == null) {
|
|
||||||
// Third, accept one with alpha but with stencil, 16-bit depth.
|
|
||||||
for (int i = 0; i < configs.length; i++) {
|
|
||||||
ConfigAttribs c = configs[i];
|
|
||||||
if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 8 && c.stencil >= 8 && c.depth >= 16) {
|
|
||||||
chosen = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chosen == null) {
|
|
||||||
// Fourth, accept one with 16-bit color but depth and stencil required.
|
|
||||||
for (int i = 0; i < configs.length; i++) {
|
|
||||||
ConfigAttribs c = configs[i];
|
|
||||||
if (c.red >= 5 && c.green >= 6 && c.blue >= 5 && c.depth >= 16 && c.stencil >= 8) {
|
|
||||||
chosen = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chosen == null) {
|
|
||||||
// Fifth, accept one with 16-bit color but depth required.
|
|
||||||
for (int i = 0; i < configs.length; i++) {
|
|
||||||
ConfigAttribs c = configs[i];
|
|
||||||
if (c.red >= 5 && c.green >= 6 && c.blue >= 5 && c.depth >= 16) {
|
|
||||||
chosen = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chosen == null) {
|
|
||||||
// Final, accept the first one in the list.
|
|
||||||
if (configs.length > 0)
|
|
||||||
chosen = configs[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chosen == null) {
|
|
||||||
throw new IllegalArgumentException("Failed to find a valid EGL config");
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.i(TAG, "Final chosen config: ");
|
|
||||||
chosen.Log();
|
|
||||||
return chosen.config;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,94 +0,0 @@
|
||||||
package org.ppsspp.ppsspp;
|
|
||||||
|
|
||||||
import javax.microedition.khronos.egl.EGLConfig;
|
|
||||||
import javax.microedition.khronos.opengles.GL10;
|
|
||||||
|
|
||||||
import android.graphics.Point;
|
|
||||||
import android.opengl.GLES20;
|
|
||||||
import android.opengl.GLSurfaceView;
|
|
||||||
import android.util.DisplayMetrics;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Display;
|
|
||||||
|
|
||||||
public class NativeRenderer implements GLSurfaceView.Renderer {
|
|
||||||
private static String TAG = "NativeRenderer";
|
|
||||||
private NativeActivity mActivity;
|
|
||||||
private boolean isDark = false;
|
|
||||||
private int dpi;
|
|
||||||
private float refreshRate;
|
|
||||||
|
|
||||||
private double dpi_scale_x;
|
|
||||||
private double dpi_scale_y;
|
|
||||||
|
|
||||||
int last_width, last_height;
|
|
||||||
|
|
||||||
NativeRenderer(NativeActivity act) {
|
|
||||||
mActivity = act;
|
|
||||||
DisplayMetrics metrics = new DisplayMetrics();
|
|
||||||
Display display = act.getWindowManager().getDefaultDisplay();
|
|
||||||
display.getMetrics(metrics);
|
|
||||||
dpi = metrics.densityDpi;
|
|
||||||
|
|
||||||
refreshRate = display.getRefreshRate();
|
|
||||||
}
|
|
||||||
|
|
||||||
double getDpiScaleX() {
|
|
||||||
return dpi_scale_x;
|
|
||||||
}
|
|
||||||
double getDpiScaleY() {
|
|
||||||
return dpi_scale_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDark(boolean d) {
|
|
||||||
isDark = d;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFixedSize(int xres, int yres, GLSurfaceView surfaceView) {
|
|
||||||
Log.i(TAG, "Setting surface to fixed size " + xres + "x" + yres);
|
|
||||||
surfaceView.getHolder().setFixedSize(xres, yres);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onDrawFrame(GL10 unused /*use GLES20*/) {
|
|
||||||
if (isDark) {
|
|
||||||
GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
|
|
||||||
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
|
||||||
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_STENCIL_BUFFER_BIT);
|
|
||||||
} else {
|
|
||||||
displayRender();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
|
|
||||||
// Log.i(TAG, "onSurfaceCreated - EGL context is new or was lost");
|
|
||||||
// Actually, it seems that it is here we should recreate lost GL objects.
|
|
||||||
displayInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSurfaceChanged(GL10 unused, int width, int height) {
|
|
||||||
Point sz = new Point();
|
|
||||||
mActivity.GetScreenSize(sz);
|
|
||||||
double actualW = sz.x;
|
|
||||||
double actualH = sz.y;
|
|
||||||
dpi_scale_x = ((double)width / (double)actualW);
|
|
||||||
dpi_scale_y = ((double)height / (double)actualH);
|
|
||||||
Log.i(TAG, "onSurfaceChanged: " + dpi_scale_x + "x" + dpi_scale_y + " (width=" + width + ", actualW=" + actualW);
|
|
||||||
int scaled_dpi = (int)((double)dpi * dpi_scale_x);
|
|
||||||
displayResize(width, height, scaled_dpi, refreshRate);
|
|
||||||
last_width = width;
|
|
||||||
last_height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not override, it's custom.
|
|
||||||
public void onDestroyed() {
|
|
||||||
displayShutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
// NATIVE METHODS
|
|
||||||
|
|
||||||
// Note: This also means "device lost" and you should reload
|
|
||||||
// all buffered objects.
|
|
||||||
public native void displayInit();
|
|
||||||
public native void displayResize(int w, int h, int dpi, float refreshRate);
|
|
||||||
public native void displayRender();
|
|
||||||
public native void displayShutdown();
|
|
||||||
}
|
|
|
@ -5,6 +5,7 @@ package org.ppsspp.ppsspp;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.graphics.Point;
|
||||||
import android.hardware.Sensor;
|
import android.hardware.Sensor;
|
||||||
import android.hardware.SensorEvent;
|
import android.hardware.SensorEvent;
|
||||||
import android.hardware.SensorEventListener;
|
import android.hardware.SensorEventListener;
|
||||||
|
@ -12,13 +13,17 @@ import android.hardware.SensorManager;
|
||||||
import android.opengl.GLSurfaceView;
|
import android.opengl.GLSurfaceView;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
// import android.os.Build;
|
// import android.os.Build;
|
||||||
// import android.util.Log;
|
// import android.util.Log;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.Display;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
import android.view.SurfaceView;
|
||||||
|
|
||||||
import com.bda.controller.*;
|
import com.bda.controller.*;
|
||||||
|
|
||||||
public class NativeGLView extends GLSurfaceView implements SensorEventListener, ControllerListener {
|
public class NativeSurfaceView extends SurfaceView implements SensorEventListener, ControllerListener {
|
||||||
private static String TAG = "NativeGLView";
|
private static String TAG = "NativeGLView";
|
||||||
private SensorManager mSensorManager;
|
private SensorManager mSensorManager;
|
||||||
private Sensor mAccelerometer;
|
private Sensor mAccelerometer;
|
||||||
|
@ -27,33 +32,36 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener,
|
||||||
// Moga controller
|
// Moga controller
|
||||||
private Controller mController = null;
|
private Controller mController = null;
|
||||||
private boolean isMogaPro = false;
|
private boolean isMogaPro = false;
|
||||||
|
private int dpi;
|
||||||
|
private float refreshRate;
|
||||||
|
|
||||||
public NativeGLView(NativeActivity activity) {
|
private double dpi_scale_x;
|
||||||
|
private double dpi_scale_y;
|
||||||
|
|
||||||
|
int last_width, last_height;
|
||||||
|
|
||||||
|
public int fixedW = 0;
|
||||||
|
public int fixedH = 0;
|
||||||
|
|
||||||
|
public NativeSurfaceView(NativeActivity activity) {
|
||||||
super(activity);
|
super(activity);
|
||||||
mActivity = activity;
|
|
||||||
|
|
||||||
/*// TODO: This would be nice.
|
DisplayMetrics metrics = new DisplayMetrics();
|
||||||
if (Build.VERSION.SDK_INT >= 11) {
|
Display display = activity.getWindowManager().getDefaultDisplay();
|
||||||
try {
|
display.getMetrics(metrics);
|
||||||
Method method_setPreserveEGLContextOnPause = GLSurfaceView.class.getMethod(
|
dpi = metrics.densityDpi;
|
||||||
"setPreserveEGLContextOnPause", new Class[] { Boolean.class });
|
|
||||||
Log.i(TAG, "Invoking setPreserveEGLContextOnPause");
|
refreshRate = display.getRefreshRate();
|
||||||
method_setPreserveEGLContextOnPause.invoke(this, true);
|
|
||||||
} catch (NoSuchMethodException e) {
|
mActivity = activity;
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
mSensorManager = (SensorManager)activity.getSystemService(Activity.SENSOR_SERVICE);
|
mSensorManager = (SensorManager)activity.getSystemService(Activity.SENSOR_SERVICE);
|
||||||
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
||||||
|
|
||||||
mController = Controller.getInstance(activity);
|
mController = Controller.getInstance(activity);
|
||||||
|
|
||||||
|
onResize(display.getWidth(), display.getHeight());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
MogaHack.init(mController, activity);
|
MogaHack.init(mController, activity);
|
||||||
Log.i(TAG, "MOGA initialized");
|
Log.i(TAG, "MOGA initialized");
|
||||||
|
@ -63,17 +71,37 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onResize(int width, int height) {
|
||||||
|
Point sz = new Point();
|
||||||
|
mActivity.GetScreenSize(sz);
|
||||||
|
double actualW = sz.x;
|
||||||
|
double actualH = sz.y;
|
||||||
|
dpi_scale_x = (width / actualW);
|
||||||
|
dpi_scale_y = (height / actualH);
|
||||||
|
Log.i(TAG, "onSurfaceChanged: " + dpi_scale_x + "x" + dpi_scale_y + " (width=" + width + ", actualW=" + actualW);
|
||||||
|
int scaled_dpi = (int)(dpi * dpi_scale_x);
|
||||||
|
NativeApp.displayResize(width, height, scaled_dpi, refreshRate);
|
||||||
|
last_width = width;
|
||||||
|
last_height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setFixedSize(int w, int h) {
|
||||||
|
fixedW = w;
|
||||||
|
fixedH = h;
|
||||||
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
|
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
|
||||||
private int getToolType(final MotionEvent ev, int pointer) {
|
private int getToolType(final MotionEvent ev, int pointer) {
|
||||||
return ev.getToolType(pointer);
|
return ev.getToolType(pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean onTouchEvent(final MotionEvent ev) {
|
public boolean onTouchEvent(final MotionEvent ev) {
|
||||||
boolean canReadToolType = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
|
boolean canReadToolType = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
|
||||||
|
|
||||||
int numTouchesHandled = 0;
|
int numTouchesHandled = 0;
|
||||||
float scaleX = (float)mActivity.getRenderer().getDpiScaleX();
|
float scaleX = (float)this.dpi_scale_x;
|
||||||
float scaleY = (float)mActivity.getRenderer().getDpiScaleY();
|
float scaleY = (float)this.dpi_scale_y;
|
||||||
for (int i = 0; i < ev.getPointerCount(); i++) {
|
for (int i = 0; i < ev.getPointerCount(); i++) {
|
||||||
int pid = ev.getPointerId(i);
|
int pid = ev.getPointerId(i);
|
||||||
int code = 0;
|
int code = 0;
|
||||||
|
@ -112,9 +140,11 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sensor management
|
// Sensor management
|
||||||
|
@Override
|
||||||
public void onAccuracyChanged(Sensor sensor, int arg1) {
|
public void onAccuracyChanged(Sensor sensor, int arg1) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onSensorChanged(SensorEvent event) {
|
public void onSensorChanged(SensorEvent event) {
|
||||||
if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) {
|
if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) {
|
||||||
return;
|
return;
|
||||||
|
@ -123,18 +153,14 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener,
|
||||||
NativeApp.accelerometer(event.values[0], event.values[1], event.values[2]);
|
NativeApp.accelerometer(event.values[0], event.values[1], event.values[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
super.onPause();
|
|
||||||
mSensorManager.unregisterListener(this);
|
mSensorManager.unregisterListener(this);
|
||||||
if (mController != null) {
|
if (mController != null) {
|
||||||
mController.onPause();
|
mController.onPause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
|
||||||
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
|
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
|
||||||
if (mController != null) {
|
if (mController != null) {
|
||||||
mController.onResume();
|
mController.onResume();
|
|
@ -114,7 +114,7 @@ public class PpssppActivity extends NativeActivity {
|
||||||
sz.y = 0;
|
sz.y = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
correctRatio(sz, (float)scale);
|
correctRatio(sz, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
// called by the C++ code through JNI. Dispatch anything we can't directly handle
|
// called by the C++ code through JNI. Dispatch anything we can't directly handle
|
||||||
|
@ -123,6 +123,7 @@ public class PpssppActivity extends NativeActivity {
|
||||||
final String cmd = command;
|
final String cmd = command;
|
||||||
final String param = parameter;
|
final String param = parameter;
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
processCommand(cmd, param);
|
processCommand(cmd, param);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue