From db633aa37794f40d7e7d71e6c958f3fbe3663a01 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 16 Dec 2015 21:37:09 +0100 Subject: [PATCH] Lots more debug logging. Terrifying compatibility hack for devices that for some reason create 16-bit buffers. Like Xperia Play. --- Common/GL/GLInterface/EGL.cpp | 143 ++++++++++++++---- Common/GL/GLInterface/EGL.h | 3 +- Common/GL/GLInterface/EGLAndroid.cpp | 18 ++- Common/GL/GLInterfaceBase.h | 2 +- UI/NativeApp.cpp | 2 +- android/jni/app-android.cpp | 20 ++- .../src/org/ppsspp/ppsspp/NativeActivity.java | 4 +- android/src/org/ppsspp/ppsspp/NativeApp.java | 2 +- .../org/ppsspp/ppsspp/NativeSurfaceView.java | 5 + 9 files changed, 155 insertions(+), 44 deletions(-) diff --git a/Common/GL/GLInterface/EGL.cpp b/Common/GL/GLInterface/EGL.cpp index 4bd159969e..a9d8cb3c71 100644 --- a/Common/GL/GLInterface/EGL.cpp +++ b/Common/GL/GLInterface/EGL.cpp @@ -25,9 +25,6 @@ void* cInterfaceEGL::GetFuncAddress(const std::string& name) void cInterfaceEGL::DetectMode() { - if (s_opengl_mode != MODE_DETECT) - return; - EGLint num_configs; bool supportsGL = false, supportsGLES2 = false, supportsGLES3 = false; std::array renderable_types = { @@ -97,8 +94,62 @@ void cInterfaceEGL::DetectMode() s_opengl_mode = GLInterfaceMode::MODE_OPENGL; // Fall back to OpenGL } +static void LogEGLConfig(EGLDisplay egl_dpy, EGLConfig config) { + EGLint red = 0, green = 0, blue = 0, alpha = 0, depth = 0, stencil = 0, format = -1, type; + + struct { + EGLint value; + const char *name; + } vals[] = { + { EGL_RED_SIZE, "EGL_RED_SIZE" }, + { EGL_GREEN_SIZE, "EGL_GREEN_SIZE" }, + { EGL_BLUE_SIZE, "EGL_BLUE_SIZE" }, + { EGL_ALPHA_SIZE, "EGL_ALPHA_SIZE" }, + { EGL_DEPTH_SIZE, "EGL_DEPTH_SIZE" }, + { EGL_STENCIL_SIZE, "EGL_STENCIL_SIZE" }, + { EGL_NATIVE_VISUAL_ID, "EGL_NATIVE_VISUAL_ID" }, + { EGL_NATIVE_VISUAL_TYPE, "EGL_NATIVE_VISUAL_TYPE" }, + { EGL_MAX_SWAP_INTERVAL, "EGL_MAX_SWAP_INTERVAL" }, + { EGL_MIN_SWAP_INTERVAL, "EGL_MIN_SWAP_INTERVAL" }, + { EGL_MIN_SWAP_INTERVAL, "EGL_MIN_SWAP_INTERVAL" }, + { EGL_NATIVE_RENDERABLE, "EGL_NATIVE_RENDERABLE" }, + { EGL_COLOR_BUFFER_TYPE, "EGL_COLOR_BUFFER_TYPE" }, + { EGL_BUFFER_SIZE, "EGL_BUFFER_SIZE" }, + { EGL_CONFIG_ID, "EGL_CONFIG_ID" }, + { EGL_SAMPLES, "EGL_SAMPLES" }, + }; + + for (int i = 0; i < (int)(sizeof(vals)/sizeof(vals[0])); i++) { + EGLint value; + eglGetConfigAttrib(egl_dpy, config, vals[i].value, &value); + INFO_LOG(G3D, " %s = %d", vals[i].name, value); + } +} + +const char *cInterfaceEGL::EGLGetErrorString(EGLint error) { + switch (error) { + case EGL_SUCCESS: return "EGL_SUCCESS"; + case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED"; + case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS"; + case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC"; + case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE"; + case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT"; + case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG"; + case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE"; + case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY"; + case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE"; + case EGL_BAD_MATCH: return "EGL_BAD_MATCH"; + case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER"; + case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP"; + case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW"; + case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; + default: + return "(UNKNOWN)"; + } +} + // Create rendering window. -bool cInterfaceEGL::Create(void *window_handle, bool core) +bool cInterfaceEGL::Create(void *window_handle, bool core, bool use16bit) { const char *s; EGLint egl_major, egl_minor; @@ -118,27 +169,43 @@ bool cInterfaceEGL::Create(void *window_handle, bool core) } INFO_LOG(G3D, "eglInitialize() succeeded\n"); - /* Detection code */ - EGLConfig config; - EGLint num_configs; + if (s_opengl_mode == MODE_DETECT) + DetectMode(); - DetectMode(); - - // attributes for a visual in RGBA format with at least - // 8 bits per color, 16 bits of depth and 8 bits of stencil. - int attribs[] = { - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + int attribs32[] = { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // Keep this first! EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 16, EGL_STENCIL_SIZE, 8, - EGL_NONE }; + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_TRANSPARENT_TYPE, EGL_NONE, + EGL_SAMPLES, 0, + EGL_NONE, 0 + }; + int attribs16[] = { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // Keep this first! + EGL_RED_SIZE, 5, + EGL_GREEN_SIZE, 6, + EGL_BLUE_SIZE, 5, + EGL_ALPHA_SIZE, 0, + EGL_DEPTH_SIZE, 16, + EGL_STENCIL_SIZE, 8, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_TRANSPARENT_TYPE, EGL_NONE, + EGL_SAMPLES, 0, + EGL_NONE, 0 + }; + int *attribs = attribs32; + if (use16bit) { + attribs = attribs16; + } EGLint ctx_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE + EGL_NONE, 0 }; switch (s_opengl_mode) { @@ -155,17 +222,32 @@ bool cInterfaceEGL::Create(void *window_handle, bool core) ctx_attribs[1] = 3; break; default: - ERROR_LOG(G3D, "Unknown opengl mode set\n"); + ERROR_LOG(G3D, "Unknown OpenGL mode set\n"); return false; break; } - if (!eglChooseConfig(egl_dpy, attribs, &config, 1, &num_configs)) { - INFO_LOG(G3D, "Error: couldn't get an EGL visual config\n"); - exit(1); + EGLConfig *configs; + EGLint num_configs; + if (!eglChooseConfig(egl_dpy, attribs, NULL, 0, &num_configs) || num_configs == 0) { + INFO_LOG(G3D, "Error: couldn't get a number of configs\n"); + eglTerminate(egl_dpy); + return false; } - INFO_LOG(G3D, "eglChooseConfig successful"); + configs = new EGLConfig[num_configs]; + + if (!eglChooseConfig(egl_dpy, attribs, configs, num_configs, &num_configs)) { + INFO_LOG(G3D, "Error: couldn't get an EGL visual config\n"); + eglTerminate(egl_dpy); + return false; + } + + INFO_LOG(G3D, "eglChooseConfig successful: num_configs=%d, choosing config 0", num_configs); + for (int i = 0; i < num_configs; i++) { + INFO_LOG(G3D, "Config %d:", i); + LogEGLConfig(egl_dpy, configs[i]); + } if (s_opengl_mode == MODE_OPENGL) eglBindAPI(EGL_OPENGL_API); @@ -173,7 +255,7 @@ bool cInterfaceEGL::Create(void *window_handle, bool core) eglBindAPI(EGL_OPENGL_ES_API); EGLNativeWindowType host_window = (EGLNativeWindowType) window_handle; - EGLNativeWindowType native_window = InitializePlatform(host_window, config); + EGLNativeWindowType native_window = InitializePlatform(host_window, configs[0]); s = eglQueryString(egl_dpy, EGL_VERSION); INFO_LOG(G3D, "EGL_VERSION = %s\n", s); @@ -187,18 +269,25 @@ bool cInterfaceEGL::Create(void *window_handle, bool core) s = eglQueryString(egl_dpy, EGL_CLIENT_APIS); 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, configs[0], EGL_NO_CONTEXT, ctx_attribs); if (!egl_ctx) { - INFO_LOG(G3D, "Error: eglCreateContext failed\n"); - exit(1); + INFO_LOG(G3D, "Error: eglCreateContext failed: %s\n", EGLGetErrorString(eglGetError())); + eglTerminate(egl_dpy); + delete[] configs; + return false; } - egl_surf = eglCreateWindowSurface(egl_dpy, config, native_window, nullptr); + egl_surf = eglCreateWindowSurface(egl_dpy, configs[0], native_window, nullptr); if (!egl_surf) { - INFO_LOG(G3D, "Error: eglCreateWindowSurface failed\n"); - exit(1); + INFO_LOG(G3D, "Error: eglCreateWindowSurface failed: native_window=%p error=%s ctx_attribs[1]==%d\n", native_window, EGLGetErrorString(eglGetError()), ctx_attribs[1]); + + eglDestroyContext(egl_dpy, egl_ctx); + eglTerminate(egl_dpy); + delete[] configs; + return false; } + delete[] configs; return true; } diff --git a/Common/GL/GLInterface/EGL.h b/Common/GL/GLInterface/EGL.h index 527af54918..cf8ed1db61 100644 --- a/Common/GL/GLInterface/EGL.h +++ b/Common/GL/GLInterface/EGL.h @@ -21,13 +21,14 @@ protected: virtual EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) = 0; virtual void ShutdownPlatform() = 0; virtual void SetInternalResolution(int internalWidth, int internalHeight) {} + const char *EGLGetErrorString(EGLint error); public: void SwapInterval(int Interval); void Swap(); void SetMode(u32 mode) { s_opengl_mode = mode; } void* GetFuncAddress(const std::string& name); - bool Create(void *window_handle, bool core); + bool Create(void *window_handle, bool core, bool use16bit) override; bool MakeCurrent(); bool ClearCurrent(); void Shutdown(); diff --git a/Common/GL/GLInterface/EGLAndroid.cpp b/Common/GL/GLInterface/EGLAndroid.cpp index 29796fae29..0d4a0e2339 100644 --- a/Common/GL/GLInterface/EGLAndroid.cpp +++ b/Common/GL/GLInterface/EGLAndroid.cpp @@ -2,17 +2,20 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include "Common/Log.h" #include "Common/GL/GLInterface/EGLAndroid.h" -EGLDisplay cInterfaceEGLAndroid::OpenDisplay() -{ +EGLDisplay cInterfaceEGLAndroid::OpenDisplay() { return eglGetDisplay(EGL_DEFAULT_DISPLAY); } -EGLNativeWindowType cInterfaceEGLAndroid::InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) -{ - EGLint format = 0; - eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &format); +EGLNativeWindowType cInterfaceEGLAndroid::InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) { + EGLint format; + if (EGL_FALSE == eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &format)) { + ERROR_LOG(G3D, "Failed getting EGL_NATIVE_VISUAL_ID: error %s", EGLGetErrorString(eglGetError())); + return NULL; + } + ANativeWindow_setBuffersGeometry(host_window, internalWidth_, internalHeight_, format); const int width = ANativeWindow_getWidth(host_window); @@ -22,6 +25,5 @@ EGLNativeWindowType cInterfaceEGLAndroid::InitializePlatform(EGLNativeWindowType return host_window; } -void cInterfaceEGLAndroid::ShutdownPlatform() -{ +void cInterfaceEGLAndroid::ShutdownPlatform() { } diff --git a/Common/GL/GLInterfaceBase.h b/Common/GL/GLInterfaceBase.h index 9e8de11303..3d9b8dd10e 100644 --- a/Common/GL/GLInterfaceBase.h +++ b/Common/GL/GLInterfaceBase.h @@ -29,7 +29,7 @@ public: virtual void SetMode(u32 mode) { s_opengl_mode = GLInterfaceMode::MODE_OPENGL; } virtual u32 GetMode() { return s_opengl_mode; } virtual void* GetFuncAddress(const std::string& name) { return nullptr; } - virtual bool Create(void *window_handle, bool core = true) { return true; } + virtual bool Create(void *window_handle, bool core = true, bool use16bit = false) = 0; virtual bool MakeCurrent() { return true; } virtual bool ClearCurrent() { return true; } virtual void Shutdown() {} diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index ecc639e3b6..7843d5e50c 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -372,7 +372,7 @@ void NativeInit(int argc, const char *argv[], const char *fileToLog = 0; const char *stateToLoad = 0; - bool gfxLog = false; + bool gfxLog = true; // Parse command line LogTypes::LOG_LEVELS logLevel = LogTypes::LINFO; for (int i = 1; i < argc; i++) { diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 164bdcffe6..9883bf8130 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -68,6 +68,7 @@ static int deviceType; static int display_dpi; static int display_xres; static int display_yres; +static int backbuffer_format; // Android PixelFormat enum static int desiredBackbufferSizeX; static int desiredBackbufferSizeY; @@ -528,12 +529,13 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_setDisplayParameters(JN display_hz = refreshRate; } -extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv *, jclass, jint bufw, jint bufh) { +extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv *, jclass, jint bufw, jint bufh, jint format) { ILOG("NativeApp.backbufferResize(%d x %d)", bufw, bufh); // pixel_*res is the backbuffer resolution. pixel_xres = bufw; pixel_yres = bufh; + backbuffer_format = format; g_dpi = (int)display_dpi; g_dpi_scale = 240.0f / (float)g_dpi; @@ -586,8 +588,20 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(J // Apparently we still have to set this through Java through setFixedSize on the bufferHolder for it to take effect... gl->SetBackBufferDimensions(desiredBackbufferSizeX, desiredBackbufferSizeY); - gl->SetMode(MODE_DETECT); - gl->Create(wnd); + gl->SetMode(MODE_OPENGLES2); + + bool use565 = false; + switch (backbuffer_format) { + case 4: // PixelFormat.RGB_565 + use565 = true; + break; + } + + if (!gl->Create(wnd, false, use565)) { + ELOG("EGL creation failed"); + // TODO: What do we do now? + return; + } gl->MakeCurrent(); if (!renderer_inited) { diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index b9ee3e195c..5ce6805957 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -380,12 +380,12 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback { @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { - Log.w(TAG, "Surface changed. Resolution: " + width + "x" + height); + Log.w(TAG, "Surface changed. Resolution: " + width + "x" + height + " Format: " + format); // Make sure we have fresh display metrics so the computations go right. // This is needed on some very old devices, I guess event order is different or something... Point sz = new Point(); updateDisplayMetrics(sz); - NativeApp.backbufferResize(width, height); + NativeApp.backbufferResize(width, height, format); mSurface = holder.getSurface(); if (mRenderLoopThread == null || !mRenderLoopThread.isAlive()) { mRenderLoopThread = new Thread(mEmulationRunner); diff --git a/android/src/org/ppsspp/ppsspp/NativeApp.java b/android/src/org/ppsspp/ppsspp/NativeApp.java index 84b2003d5d..e15252191a 100644 --- a/android/src/org/ppsspp/ppsspp/NativeApp.java +++ b/android/src/org/ppsspp/ppsspp/NativeApp.java @@ -24,7 +24,7 @@ public class NativeApp { public static native int getDesiredBackbufferHeight(); public static native void setDisplayParameters(int display_xres, int display_yres, int dpi, float refreshRate); - public static native void backbufferResize(int bufferWidth, int bufferHeight); + public static native void backbufferResize(int bufferWidth, int bufferHeight, int format); public static native boolean isLandscape(); public static native boolean isAtTopLevel(); diff --git a/android/src/org/ppsspp/ppsspp/NativeSurfaceView.java b/android/src/org/ppsspp/ppsspp/NativeSurfaceView.java index 81d8a22adc..f0eb2369e3 100644 --- a/android/src/org/ppsspp/ppsspp/NativeSurfaceView.java +++ b/android/src/org/ppsspp/ppsspp/NativeSurfaceView.java @@ -7,6 +7,7 @@ package org.ppsspp.ppsspp; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; +import android.graphics.PixelFormat; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; @@ -42,8 +43,12 @@ public class NativeSurfaceView extends SurfaceView implements SensorEventListene if (fixedW != 0 && fixedH != 0) { Log.i(TAG, "Setting surface holder to use a fixed size of " + fixedW + "x" + fixedH + " pixels"); this.getHolder().setFixedSize(fixedW, fixedH); + } else { + Log.i(TAG, "Using default backbuffer size."); } + // this.getHolder().setFormat(PixelFormat.RGBA_8888); + try { MogaHack.init(mController, activity); Log.i(TAG, "MOGA initialized");