From e6f1ab653906fcd36d415f0ddedffadcaf4176ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zsolt=20Sz=2E=20Sztup=C3=A1k?= Date: Mon, 6 Jan 2020 18:46:56 +0000 Subject: [PATCH] Fix SDL letterboxing on Android builds On Android calling `SDL_RenderSetLogicalSize` with dimensions having a different aspect ratio than the screen will cause letterboxing with blinking garbage data in that areas (instead of having black bars). This is annoying and makes the game really hard to play. This change will make sure that on Android `SDL_RenderSetLogicalSize` will always be called with dimensions where the aspect ratio is the same as the screen to make sure there is no letterboxing. The only problem with this is that during drawing the adventure map nothing will clear out the areas that would have been letterboxes, so there is an added explicit clear screen command for `totalRedraw()`. The changes are only applied to Android builds in order not to affect PC builds - but some changes, especially clearing the screen could be easily added to the PC builds as well --- client/CMT.cpp | 33 +++++++++++++++++++++++++++++++++ client/gui/CGuiHandler.cpp | 3 +++ 2 files changed, 36 insertions(+) diff --git a/client/CMT.cpp b/client/CMT.cpp index 874a8203f..8b99f4cd8 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -1056,6 +1056,39 @@ static bool recreateWindow(int w, int h, int bpp, bool fullscreen, int displayIn #ifdef VCMI_ANDROID mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex),SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), 0, 0, SDL_WINDOW_FULLSCREEN); + + // SDL on Android doesn't do proper letterboxing, and will show an annoying flickering in the blank space in case you're not using the full screen estate + // That's why we need to make sure our width and height we'll use below have the same aspect ratio as the screen itself to ensure we fill the full screen estate + + SDL_Rect screenRect; + + if(SDL_GetDisplayBounds(0, &screenRect) == 0) + { + int screenWidth, screenHeight; + double aspect; + + screenWidth = screenRect.w; + screenHeight = screenRect.h; + + aspect = (double)screenWidth / (double)screenHeight; + + logGlobal->info("Screen size and aspect ration: %dx%d (%lf)", screenWidth, screenHeight, aspect); + + if((double)w / aspect > (double)h) + { + h = (int)round((double)w / aspect); + } + else + { + w = (int)round((double)h * aspect); + } + + logGlobal->info("Changing logical screen size to %dx%d", w, h); + } + else + { + logGlobal->error("Can't fix aspect ratio for screen"); + } #else if(fullscreen) diff --git a/client/gui/CGuiHandler.cpp b/client/gui/CGuiHandler.cpp index 3910338e7..9af279bb7 100644 --- a/client/gui/CGuiHandler.cpp +++ b/client/gui/CGuiHandler.cpp @@ -162,6 +162,9 @@ std::shared_ptr CGuiHandler::topInt() void CGuiHandler::totalRedraw() { +#ifdef VCMI_ANDROID + SDL_FillRect(screen2, NULL, SDL_MapRGB(screen2->format, 0, 0, 0)); +#endif for(auto & elem : objsToBlit) elem->showAll(screen2); blitAt(screen2,0,0,screen);