SDL
SDL copied to clipboard
Android wrong pixel format information
Hello, on android when I use SDL_GetDisplayMode function before creating window it always has bad pixel format - RGB_565. When I use it just after creating window, it most of the time has good pixel format(RGBX_8888), but sometimes RGB_565. But when I use it some time after creating window (I added 300ms delay), it seems to work every time.
#include <SDL.h>
void logDisplayModes() {
SDL_Log("SDL_GetNumVideoDisplays(): %i", SDL_GetNumVideoDisplays());
int display_in_use = 0;
SDL_DisplayMode mode;
int display_mode_count = SDL_GetNumDisplayModes(display_in_use);
if (display_mode_count < 1) {
SDL_Log("SDL_GetNumDisplayModes failed: %s", SDL_GetError());
}
SDL_Log("SDL_GetNumDisplayModes: %i", display_mode_count);
for (int i = 0; i < display_mode_count; ++i) {
if (SDL_GetDisplayMode(display_in_use, i, &mode) != 0) {
SDL_Log("SDL_GetDisplayMode failed: %s", SDL_GetError());
}
int f = mode.format;
SDL_Log("Mode %i\tbpp %i\t%s\t%i x %i",
i, SDL_BITSPERPIXEL(f),
SDL_GetPixelFormatName(f),
mode.w, mode.h);
}
}
int main(int argc, char* argv[]) {
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0) {
SDL_Log("SDL init failed: %s", SDL_GetError());
SDL_ClearError();
return 0;
}
int width = 1080;
int height = 2160;
uint32_t flags = 0;
#ifdef ANDROID
flags = SDL_WINDOW_FULLSCREEN;
#endif
logDisplayModes(); // this one outputs RGB_565
SDL_Window* window = SDL_CreateWindow("AndroidSdl", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, flags);
if (!window) {
SDL_Log("Creating window failed: %s", SDL_GetError());
SDL_ClearError();
return 0;
}
SDL_Delay(300); // without this delay sometimes (1) and (2) outputs RGB_565
logDisplayModes(); // (1) outputs RGBX8888
uint32_t pixelFormat = SDL_GetWindowPixelFormat(window); // (2) outputs RGBX8888
SDL_Log("Pixel Format == %u %s\n",pixelFormat, SDL_GetPixelFormatName(pixelFormat));
SDL_Event event;
while(true) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
return 0;
}
}
SDL_Surface* screenSurf = SDL_GetWindowSurface(window);
if(screenSurf == nullptr) {
SDL_Log("((SDL))screen surface was nullptr");
return 0;
}
SDL_FillRect(screenSurf, nullptr, 0xff00ff00);
if(SDL_UpdateWindowSurface(window) == -1) {
SDL_Log("((SDL))Error during update window surface %s", SDL_GetError());
if(window == nullptr) {
return 0;
}
}
}
return 0;
}
Logs without delay and bad pixel format(sometimes is same as with delay):
44931:08-07 16:23:47.583 9575 9575 V SDL : Device: X00TD
44932:08-07 16:23:47.583 9575 9575 V SDL : Model: Zenfone Max Pro M1
44933:08-07 16:23:47.583 9575 9575 V SDL : onCreate()
44934:08-07 16:23:47.589 9575 9575 V SDL : nativeSetupJNI()
44935:08-07 16:23:47.591 9575 9575 V SDL : AUDIO nativeSetupJNI()
44936:08-07 16:23:47.591 9575 9575 V SDL : CONTROLLER nativeSetupJNI()
44939:08-07 16:23:47.638 9575 9575 V SDL : onStart()
44940:08-07 16:23:47.641 9575 9575 V SDL : onResume()
44952:08-07 16:23:47.700 9575 9575 V SDL : surfaceCreated()
44953:08-07 16:23:47.700 9575 9575 V SDL : surfaceChanged()
44954:08-07 16:23:47.700 9575 9575 V SDL : Window size: 1080x1971
44955:08-07 16:23:47.701 9575 9575 V SDL : Device size: 1080x2160
44961:08-07 16:23:47.710 9575 9599 V SDL : Running main function SDL_main from library /data/app/~~KvNPLJtl07hw8hMl2Bxitw==/org.libsdl.app-Ug1Hn5Jo5nGX79hDDToaYg==/lib/arm64/libmain.so
44962:08-07 16:23:47.710 9575 9599 V SDL : nativeRunMain()
44969:08-07 16:23:47.720 9575 9599 I SDL/APP : SDL_GetNumVideoDisplays(): 1
44971:08-07 16:23:47.721 9575 9599 I SDL/APP : SDL_GetNumDisplayModes: 1
44972:08-07 16:23:47.721 9575 9599 I SDL/APP : Mode 0 bpp 16 SDL_PIXELFORMAT_RGB565 1080 x 2160
44974:08-07 16:23:47.726 9575 9599 V SDL : setOrientation() requestedOrientation=7 width=1080 height=2160 resizable=false hint=
44978:08-07 16:23:47.729 9575 9599 I SDL/APP : pixel format wanted SDL_PIXELFORMAT_RGBX8888 (2), got SDL_PIXELFORMAT_RGBX8888 (2)
44981:08-07 16:23:47.783 1454 1561 I ActivityTaskManager: Displayed org.libsdl.app/.SDLActivity: +406ms
44983:08-07 16:23:47.817 9575 9575 V SDL : surfaceChanged()
44984:08-07 16:23:47.817 9575 9575 V SDL : Window size: 1080x2160
44985:08-07 16:23:47.817 9575 9575 V SDL : Device size: 1080x2160
44986:08-07 16:23:47.818 9575 9599 I SDL/APP : SDL_GetNumVideoDisplays(): 1
44987:08-07 16:23:47.818 9575 9599 I SDL/APP : SDL_GetNumDisplayModes: 1
44988:08-07 16:23:47.818 9575 9599 I SDL/APP : Mode 0 bpp 16 SDL_PIXELFORMAT_RGB565 1080 x 2160
44989:08-07 16:23:47.818 9575 9599 I SDL/APP : Pixel Format == 353701890 SDL_PIXELFORMAT_RGB565
44990:08-07 16:23:47.830 9575 9575 V SDL : onWindowFocusChanged(): true
44991:08-07 16:23:47.830 9575 9575 V SDL : nativeFocusChanged()
Logs with delay:
44726:08-07 16:23:43.318 9514 9514 V SDL : Device: X00TD
44727:08-07 16:23:43.318 9514 9514 V SDL : Model: Zenfone Max Pro M1
44728:08-07 16:23:43.318 9514 9514 V SDL : onCreate()
44729:08-07 16:23:43.324 9514 9514 V SDL : nativeSetupJNI()
44730:08-07 16:23:43.325 9514 9514 V SDL : AUDIO nativeSetupJNI()
44731:08-07 16:23:43.325 9514 9514 V SDL : CONTROLLER nativeSetupJNI()
44735:08-07 16:23:43.371 9514 9514 V SDL : onStart()
44736:08-07 16:23:43.374 9514 9514 V SDL : onResume()
44747:08-07 16:23:43.429 9514 9514 V SDL : surfaceCreated()
44748:08-07 16:23:43.429 9514 9514 V SDL : surfaceChanged()
44750:08-07 16:23:43.430 9514 9514 V SDL : Window size: 1080x1971
44751:08-07 16:23:43.430 9514 9514 V SDL : Device size: 1080x2160
44757:08-07 16:23:43.439 9514 9537 V SDL : Running main function SDL_main from library /data/app/~~KvNPLJtl07hw8hMl2Bxitw==/org.libsdl.app-Ug1Hn5Jo5nGX79hDDToaYg==/lib/arm64/libmain.so
44758:08-07 16:23:43.439 9514 9537 V SDL : nativeRunMain()
44762:08-07 16:23:43.449 9514 9537 I SDL/APP : SDL_GetNumVideoDisplays(): 1
44763:08-07 16:23:43.449 9514 9537 I SDL/APP : SDL_GetNumDisplayModes: 1
44764:08-07 16:23:43.449 9514 9537 I SDL/APP : Mode 0 bpp 16 SDL_PIXELFORMAT_RGB565 1080 x 2160
44766:08-07 16:23:43.454 9514 9537 V SDL : setOrientation() requestedOrientation=7 width=1080 height=2160 resizable=false hint=
44770:08-07 16:23:43.458 9514 9537 I SDL/APP : pixel format wanted SDL_PIXELFORMAT_RGBX8888 (2), got SDL_PIXELFORMAT_RGBX8888 (2)
44777:08-07 16:23:43.516 1454 1561 I ActivityTaskManager: Displayed org.libsdl.app/.SDLActivity: +409ms
44779:08-07 16:23:43.553 9514 9514 V SDL : surfaceChanged()
44780:08-07 16:23:43.553 9514 9514 V SDL : Window size: 1080x2160
44781:08-07 16:23:43.553 9514 9514 V SDL : Device size: 1080x2160
44782:08-07 16:23:43.554 9514 9537 I SDL/APP : SDL_GetNumVideoDisplays(): 1
44783:08-07 16:23:43.554 9514 9537 I SDL/APP : SDL_GetNumDisplayModes: 1
44784:08-07 16:23:43.554 9514 9537 I SDL/APP : Mode 0 bpp 24 SDL_PIXELFORMAT_RGBX8888 1080 x 2160
44785:08-07 16:23:43.554 9514 9537 I SDL/APP : Pixel Format == 371595268 SDL_PIXELFORMAT_RGBX8888
44786:08-07 16:23:43.566 9514 9514 V SDL : onWindowFocusChanged(): true
44787:08-07 16:23:43.566 9514 9514 V SDL : nativeFocusChanged()
yes, this is true. in fact the variable is by default RGB_565. https://github.com/libsdl-org/SDL/blob/main/src/video/android/SDL_androidvideo.c#L67
When the android window is created (java call surfaceChanged), it asynchronously updates the value. maybe you can wait for an event to have a valid value (maybe SDL_WINDOWEVENT_RESTORED).
some workaround:
1/ If you create yourself the SDL_Renderer, the value should be ok, after SDL_CreateRenderer is called().
2/ there used to be issues on some phone.. and we would always set SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); and so the format would always be 565
Thank you for reply. I tried adding SDL_GL_SetAttribute[...], but it doesn't work for me(pixel format is RGBX888). Maybe I'm doing something wrong. Do you have example that should work? Because having only one pixel format would be very helpful for me. Here I tried with SDL_Renderer(it doesn't work either way), but I would prefer to not use it, because rendering SDL_Surface seems to be faster with SDL_UpdateWindowSurface.
Here is code:
int main(int argc, char* argv[]) {
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0) {
SDL_Log("SDL init failed: %s", SDL_GetError());
SDL_ClearError();
return 0;
}
int width = 1080;
int height = 2160;
uint32_t flags = 0; // also tried with SDL_WINDOW_OPENGL
#ifdef ANDROID
flags |= SDL_WINDOW_FULLSCREEN;
#endif
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
SDL_Window* window = SDL_CreateWindow("AndroidSdl", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, flags);
if (!window) {
SDL_Log("Creating window failed: %s", SDL_GetError());
SDL_ClearError();
return 0;
}
SDL_Renderer* rend = SDL_CreateRenderer(window, -1, 0);
SDL_Delay(300); // without this delay sometimes (1) and (2) outputs RGB_565
logDisplayModes(); // (1) outputs RGBX8888
uint32_t pixelFormat = SDL_GetWindowPixelFormat(window); // (2) outputs RGBX8888
SDL_Log("Pixel Format == %u %s\n",pixelFormat, SDL_GetPixelFormatName(pixelFormat));
SDL_Event event;
while(true) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
return 0;
}
}
//SDL_Surface* screenSurf = SDL_GetWindowSurface(window);
//if(screenSurf == nullptr) {
// SDL_Log("((SDL))screen surface was nullptr");
// return 0;
//}
//SDL_FillRect(screenSurf, nullptr, 0xff00ff00);
//if(SDL_UpdateWindowSurface(window) == -1) {
// SDL_Log("((SDL))Error during update window surface %s", SDL_GetError());
// if(window == nullptr) {
// return 0;
// }
//}
}
return 0;
}
can you add also :
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
after SDL_Init() and before the SDL_CreateWindow(). So the place is corret.
The line interesting for you is:
SDL/APP : pixel format wanted SDL_PIXELFORMAT_RGBX8888 (2), got SDL_PIXELFORMAT_RGBX8888 (2)
Here, EGL context requests (and got) a 8888 pixel format
Using the SDL_Renderer should be the prefered way. You create your SDL_Texture once, and use them to render. You can also createSDL_Texture with STREAMING access for some operation, if you need to modify them. it's up to you anyway.
I tried adding the SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0), but still EGL requests 8888. I tried it on linux, and pixel format, also doesn't change (it is rgb888 as before).
just to be sure: you added the 4 lines:
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
there is a "FAVOR_TRUECOLOR" define: https://github.com/libsdl-org/SDL/blob/main/src/video/SDL_egl.c#L889
can you try to un-activate it ? maybe this promote a 565 to 888 context (please copy paste the "SDL/APP : pixel format wanted" log line)
Eventually, other try: by-pass the code that is meant to find the closest config. https://github.com/libsdl-org/SDL/blob/main/src/video/SDL_egl.c#L833 at this line, just return the first config:
_this->egl_data->egl_config = configs[0];
return 0;
Logs with
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
pixel format wanted SDL_PIXELFORMAT_RGBX8888 (2), got SDL_PIXELFORMAT_RGBX8888 (2)
With deactivated FAVOR_TRUECOLOR define:
pixel format wanted SDL_PIXELFORMAT_RGB565 (4), got SDL_PIXELFORMAT_UNKNOWN (277)
With
_this->egl_data->egl_config = configs[0];
return 0;
pixel format wanted SDL_PIXELFORMAT_RGBX8888 (2), got SDL_PIXELFORMAT_RGBX8888 (2)
So it looks like the FAVOR_TRUECOLOR define prevents you to get the the 565 configuration, because it promotes your request as a RGB888 request.
But there is a second thing: when you request 565, it gives you back something unknown. This is the value returned by ANativeWindow_getFormat() in SDL code ( https://developer.android.com/ndk/reference/group/a-native-window#anativewindow_getformat ), and it matches none of the AHARDWAREBUFFER_FORMAT_ enumeration.) ( https://android.googlesource.com/platform/frameworks/native/+/master/libs/nativewindow/include/android/hardware_buffer.h?autodive=0%2F%2F#59 )
But the 277 seems to have some sense anyway, because it is some OEM specific HAL formats https://android.googlesource.com/platform/hardware/qcom/display/+/master/msm8909/gralloc/gralloc_priv.h#127 #define HAL_PIXEL_FORMAT_BGR_565 0x115 maybe we can just make SDL aware of it
Thank you, now it works. :)
ok great ! can you tell which device you're using for the record ?
I'm using asus zenfone max pro m1. Also (I don't know if it matters), I have custom android ROM (lineageos 19, android 12).