| Summary: | Wrong backbuffer pixel format on Android, keep getting RGB_565 | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Onat Turkcuoglu <onattoglu> |
| Component: | video | Assignee: | Sylvain <sylvain.becker> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | normal | ||
| Priority: | P2 | ||
| Version: | HG 2.1 | ||
| Hardware: | ARM | ||
| OS: | Android (All) | ||
|
Description
Onat Turkcuoglu
2016-01-28 03:48:21 UTC
I think you need to modify SDLActivity.java to do that :
public SDLSurface(Context context) {
super(context);
getHolder().addCallback(this);
getHolder().setFormat(PixelFormat.RGBA_8888); // Add this line & set the format there.
Sylvain, shouldn't we be taking the surface format from the desired EGL depth? Indeed you're right, it seems enough to set:
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
After that, the calls to "eglGetConfigAttrib" and "ANativeWindow_setBuffersGeometry" report and use a "format == 1 ".
(https://hg.libsdl.org/SDL/file/f7abcb63e51e/src/video/SDL_egl.c#l726 ).
Which means WINDOW_FORMAT_RGBA_8888. (see the file android/native_window.h)
But, what is strange is that the SDLActivity java function surfaceChanged would still report RGB_565.
https://developer.android.com/reference/android/view/SurfaceHolder.Callback.html#surfaceChanged(android.view.SurfaceHolder,%20int,%20int,%20int)
(for the first call that could make sense (default value), then egl re-configure the java surface, but after some foreground/background, surfaceChanged still reports RGB_565)
Android ndk: android/native_window.h
26 /*
27 * Pixel formats that a window can use.
28 */
29 enum {
30 WINDOW_FORMAT_RGBA_8888 = 1,
31 WINDOW_FORMAT_RGBX_8888 = 2,
32 WINDOW_FORMAT_RGB_565 = 4,
33 };
88 /*
89 * Change the format and size of the window buffers.
90 *
91 * The width and height control the number of pixels in the buffers, not the
92 * dimensions of the window on screen. If these are different than the
93 * window's physical size, then it buffer will be scaled to match that size
94 * when compositing it to the screen.
95 *
96 * For all of these parameters, if 0 is supplied then the window's base
97 * value will come back in force.
98 *
99 * width and height must be either both zero or both non-zero.
100 *
101 */
102 int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window,
103
I have fixed in: https://hg.libsdl.org/SDL/rev/82f9397db3e7 Once you have the EGL format, it calls "Android_JNI_SetSurfaceViewFormat" to reconfigure the java SurfaceView holder format with it. (Not much difference, but maybe it's the reason for the black screen on some phone ..) Marked as fixed! A corner from the patch is fixed here: https://hg.libsdl.org/SDL/rev/bedfecf09e71 Test-case: Set SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); So that it will trigger a SurfaceView holder reconfiguration after the window is created (eg surfaceDestroyed/Created/Change sequence). Add a SDL_Delay(500) and start rendering. (This is for the test-case, but it can be considered as loading resources). - event loop is filled with SDL_WINDOWEVENT_ENTER SDL_WINDOWEVENT_FOCUS_LOST SDL_WINDOWEVENT_MINIMIZED SDL_APP_WILL ENTER BACKGROUND SDL_APP_DID ENTER BACKGROUND SDL_APP_WILL ENTER FOREGROUND SDL_APP_DID ENTER FOREGROUND SDL_WINDOWEVENT_FOCUS_GAINED SDL_WINDOWEVENT_RESTORED - The extra surfaceDestroyed/Created/Change is destroying EGL_Surface, Creating a new one, but not doing MakeCurrent. Application starts polling, and render with no context made current. First eglSwapBuffers reports EGL_BAD_SURFACE. At second polling, it does the pause/resume, hence backup-restore and make current and it renders. With the patch, backup-restore and make current is done after SDL_APP_DID ENTER BACKGROUND is consumed. Another corner case: https://hg.libsdl.org/SDL/rev/b5f8e6c420c2 Can be triggered by putting the screen off (manually), as soon as the app starts |