From a95f91bceaa7dc47af8fed021699a95d4c94b380 Mon Sep 17 00:00:00 2001 From: Sylvain Becker Date: Wed, 2 Jan 2019 18:06:33 +0100 Subject: [PATCH] Fixed bug 3250 - Wrong backbuffer pixel format on Android, keep getting RGB_565 Use the egl format to reconfigure java SurfaceView holder format. If there is a change, it triggers a surfaceDestroyed/Created/Change sequence. --- .../main/java/org/libsdl/app/SDLActivity.java | 35 +++++++++++++++++++ src/core/android/SDL_android.c | 25 ++++++++++++- src/core/android/SDL_android.h | 1 + src/video/SDL_egl.c | 5 +++ 4 files changed, 65 insertions(+), 1 deletion(-) diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index a58ce344756ff..b4d5c461da536 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -530,6 +530,7 @@ public static void handleNativeExit() { static final int COMMAND_CHANGE_TITLE = 1; static final int COMMAND_CHANGE_WINDOW_STYLE = 2; static final int COMMAND_TEXTEDIT_HIDE = 3; + static final int COMMAND_CHANGE_SURFACEVIEW_FORMAT = 4; static final int COMMAND_SET_KEEP_SCREEN_ON = 5; protected static final int COMMAND_USER = 0x8000; @@ -627,6 +628,32 @@ public void handleMessage(Message msg) { } break; } + case COMMAND_CHANGE_SURFACEVIEW_FORMAT: + { + int format = ((int)msg.obj); + int pf; + + if (SDLActivity.mSurface == null) { + return; + } + + SurfaceHolder holder = SDLActivity.mSurface.getHolder(); + if (holder == null) { + return; + } + + if (format == 1) { + pf = PixelFormat.RGBA_8888; + } else if (format == 2) { + pf = PixelFormat.RGBX_8888; + } else { + pf = PixelFormat.RGB_565; + } + + holder.setFormat(pf); + + break; + } default: if ((context instanceof SDLActivity) && !((SDLActivity) context).onUnhandledMessage(msg.arg1, msg.obj)) { Log.e(TAG, "error handling message, command is " + msg.arg1); @@ -1032,6 +1059,14 @@ public static Surface getNativeSurface() { return SDLActivity.mSurface.getNativeSurface(); } + /** + * This method is called by SDL using JNI. + */ + public static void setSurfaceViewFormat(int format) { + mSingleton.sendCommand(COMMAND_CHANGE_SURFACEVIEW_FORMAT, format); + return; + } + // Input /** diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index dd20a2bb0b2e7..9a3ba2b398da7 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -222,6 +222,7 @@ static jclass mActivityClass; /* method signatures */ static jmethodID midGetNativeSurface; +static jmethodID midSetSurfaceViewFormat; static jmethodID midSetActivityTitle; static jmethodID midSetWindowStyle; static jmethodID midSetOrientation; @@ -327,6 +328,8 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass c midGetNativeSurface = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, "getNativeSurface","()Landroid/view/Surface;"); + midSetSurfaceViewFormat = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, + "setSurfaceViewFormat","(I)V"); midSetActivityTitle = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, "setActivityTitle","(Ljava/lang/String;)Z"); midSetWindowStyle = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, @@ -374,7 +377,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass c midSetRelativeMouseEnabled = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, "setRelativeMouseEnabled", "(Z)Z"); - if (!midGetNativeSurface || + if (!midGetNativeSurface || !midSetSurfaceViewFormat || !midSetActivityTitle || !midSetWindowStyle || !midSetOrientation || !midGetContext || !midIsTablet || !midIsAndroidTV || !midInputGetInputDeviceIds || !midSendMessage || !midShowTextInput || !midIsScreenKeyboardShown || !midClipboardSetText || !midClipboardGetText || !midClipboardHasText || @@ -964,6 +967,26 @@ ANativeWindow* Android_JNI_GetNativeWindow(void) return anw; } +void Android_JNI_SetSurfaceViewFormat(int format) +{ + JNIEnv *mEnv = Android_JNI_GetEnv(); + int new_format = 0; + + /* Format from android/native_window.h, + * convert to temporary arbitrary values, + * then to java PixelFormat */ + if (format == WINDOW_FORMAT_RGBA_8888) { + new_format = 1; + } else if (format == WINDOW_FORMAT_RGBX_8888) { + new_format = 2; + } else if (format == WINDOW_FORMAT_RGB_565) { + /* Default */ + new_format = 0; + } + + (*mEnv)->CallStaticVoidMethod(mEnv, mActivityClass, midSetSurfaceViewFormat, new_format); +} + void Android_JNI_SetActivityTitle(const char *title) { JNIEnv *mEnv = Android_JNI_GetEnv(); diff --git a/src/core/android/SDL_android.h b/src/core/android/SDL_android.h index b2ff32ea659dd..1277a7487ad02 100644 --- a/src/core/android/SDL_android.h +++ b/src/core/android/SDL_android.h @@ -44,6 +44,7 @@ extern void Android_JNI_ShowTextInput(SDL_Rect *inputRect); extern void Android_JNI_HideTextInput(void); extern SDL_bool Android_JNI_IsScreenKeyboardShown(void); extern ANativeWindow* Android_JNI_GetNativeWindow(void); +extern void Android_JNI_SetSurfaceViewFormat(int format); extern int Android_JNI_GetDisplayDPI(float *ddpi, float *xdpi, float *ydpi); diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c index dfaf28eb9e9ea..685c65b0fb3c8 100644 --- a/src/video/SDL_egl.c +++ b/src/video/SDL_egl.c @@ -27,6 +27,7 @@ #endif #if SDL_VIDEO_DRIVER_ANDROID #include +#include "../core/android/SDL_android.h" #endif #include "SDL_sysvideo.h" @@ -885,6 +886,10 @@ SDL_EGL_CreateSurface(_THIS, NativeWindowType nw) EGL_NATIVE_VISUAL_ID, &format); ANativeWindow_setBuffersGeometry(nw, 0, 0, format); + + /* Update SurfaceView holder format. + * May triggers a sequence surfaceDestroyed(), surfaceCreated(), surfaceChanged(). */ + Android_JNI_SetSurfaceViewFormat(format); } #endif if (_this->gl_config.framebuffer_srgb_capable) {