Blue/Purple Screen on New Android

You can get help here if Freeciv doesn't start on your computer, or if you keep getting fatal errors while playing etc.
javaxubuntu
Posts: 32
Joined: Wed Sep 20, 2017 10:57 am

Re: Blue/Purple Screen on New Android

Postby javaxubuntu » Sun Dec 30, 2018 7:59 pm

Do you mean the main menu displays correctly during 1 second, then have the bug during 1 second, then this sequence repeats ? It's a useful information for me.

mjjunk
Posts: 14
Joined: Sat Dec 01, 2018 4:02 pm

Re: Blue/Purple Screen on New Android

Postby mjjunk » Sun Dec 30, 2018 9:44 pm

The splash screen shows correctly for one second and then it changes and never corrects itself even when going to the main menu for the load and setup options.

louis94
Hardened
Posts: 215
Joined: Thu Apr 25, 2013 10:17 pm
Location: Belgium

Re: Blue/Purple Screen on New Android

Postby louis94 » Sun Dec 30, 2018 11:41 pm

It looks like an issue with color management. Maybe the wrong color space is somehow selected at startup? I'd try to reproduce with some basic SDL demos to rule out an upstream issue first.

javaxubuntu
Posts: 32
Joined: Wed Sep 20, 2017 10:57 am

Re: Blue/Purple Screen on New Android

Postby javaxubuntu » Tue Jan 01, 2019 10:43 am

louis94 wrote:Maybe the wrong color space is somehow selected at startup?

It's possible. But it happens only on some devices, and the options "disable hw overlays" and "force 4x msaa" fix the problem. I don't have skills in SDL but I think these options are not related to color space. Because this bug happens on powerful devices, it seems that slowing down the GPU helps to fix the problem.
I'm searching for the portion of code that creates the bug, so I've made a new APK that moves the splash screen during startup, and I need to know where is this splash screen when the bug happens.

mjjunk
Posts: 14
Joined: Sat Dec 01, 2018 4:02 pm

Re: Blue/Purple Screen on New Android

Postby mjjunk » Tue Jan 01, 2019 2:06 pm

It changes color before it moves for the first time.

javaxubuntu
Posts: 32
Joined: Wed Sep 20, 2017 10:57 am

Re: Blue/Purple Screen on New Android

Postby javaxubuntu » Tue Jan 01, 2019 5:25 pm

I've added more steps in the beginning of game load. In this new APK, the splash screen should move to the right first (then to the bottom, then left...)
When does the bug appear?

mjjunk
Posts: 14
Joined: Sat Dec 01, 2018 4:02 pm

Re: Blue/Purple Screen on New Android

Postby mjjunk » Tue Jan 01, 2019 5:53 pm

The bug appears in this install right at the beginning. I didn't get the brief non bug part this time.

javaxubuntu
Posts: 32
Joined: Wed Sep 20, 2017 10:57 am

Re: Blue/Purple Screen on New Android

Postby javaxubuntu » Tue Jan 01, 2019 6:41 pm

This is weird because I've added some code to wait during 5 seconds (time.sleep). Without this, the game loads and the bug appears later, but with the 5 seconds wait the bug appears immediately.
lib/android.pyx

Code: Select all

     display_splash('userdata/presplash.png', (255, 255, 255))
+    time.sleep(5)
     os.chdir(get_internal_storage() + '/package')
+    display_splash('userdata/presplash.png', (255, 255, 255),300,0) # move to the right
+    time.sleep(2)

It seems that making the CPU busy avoids the problem.
louis94 wrote:I'd try to reproduce with some basic SDL demos to rule out an upstream issue first.

I'll try this, but I don't know when I've time to do this.

louis94
Hardened
Posts: 215
Joined: Thu Apr 25, 2013 10:17 pm
Location: Belgium

Re: Blue/Purple Screen on New Android

Postby louis94 » Tue Jan 01, 2019 11:40 pm

I found this SDL bug (several years old \o/): https://bugzilla.libsdl.org/show_bug.cgi?id=2291
This suggests that using a wrong pixel format may cause similar behavior. This app displays a list of supported pixel formats.

Maybe the software renderer would not have this problem? In graphics.pyx:

Code: Select all

  def create_window(size, hidden=False, fullscreen=False):
      global _window, _window_handle
      w, h = size
-     flags = SDL_WINDOW_OPENGL # we need OpenGL, software renderer is shit
+     flags = 0 # Try software renderer
      if hidden:
          flags |= SDL_WINDOW_HIDDEN
      if fullscreen:
          flags |= SDL_WINDOW_FULLSCREEN
      wnd = SDL_CreateWindow("touchciv", 0, 0, w, h, flags)
      _window_handle = wnd
-     renderer = SDL_CreateRenderer(wnd, -1, SDL_RENDERER_ACCELERATED)
+     renderer = SDL_CreateRenderer(wnd, -1, SDL_RENDERER_SOFTWARE)
      if not renderer:
          raise SDLError()
  _window = _make_surface(renderer, NULL, size, "window")

javaxubuntu
Posts: 32
Joined: Wed Sep 20, 2017 10:57 am

Re: Blue/Purple Screen on New Android

Postby javaxubuntu » Wed Jan 02, 2019 11:08 pm

I've added a new APK with software rendering and also some debugging information inside pl.org.zielinscy.freeciv.debug/saves/more.log:

Code: Select all

load_image userdata/intro.jpg : format 0x17101803
load_image userdata/options.png : format 0x16762004

(this is the SDL_PixelFormatEnum value)
This renderer is very slow and you can expect big black surfaces in the map view, because the app uses a patch that don't seem to work with software rendering.

All I've found about pixel format in the source code is:

Code: Select all

grep -ril pixelformat android/project/src/ android/project/jni/src/ lib/ src/
android/project/src/main/java/org/libsdl/app/SDLActivity.java (part of SDL2-2.0.9.tar.gz)
android/project/jni/src/graphics.c (copy of lib/graphics.c generated from graphics.pyx)
lib/SDL.pxd
lib/graphics.pyx
lib/graphics.c (generated from graphics.pyx)

Inside SDLActivity.java:

Code: Select all


    // Called when the surface is resized
    @Override
    public void surfaceChanged(SurfaceHolder holder,
                               int format, int width, int height) {
        Log.v("SDL", "surfaceChanged()");

        if (SDLActivity.mSingleton == null) {
            return;
        }

        int sdlFormat = 0x15151002; // SDL_PIXELFORMAT_RGB565 by default
        switch (format) {
        case PixelFormat.A_8:
            Log.v("SDL", "pixel format A_8");
            break;
        case PixelFormat.LA_88:
            Log.v("SDL", "pixel format LA_88");
            break;
        case PixelFormat.L_8:
            Log.v("SDL", "pixel format L_8");
            break;
        case PixelFormat.RGBA_4444:
            Log.v("SDL", "pixel format RGBA_4444");
            sdlFormat = 0x15421002; // SDL_PIXELFORMAT_RGBA4444
            break;
        case PixelFormat.RGBA_5551:
            Log.v("SDL", "pixel format RGBA_5551");
            sdlFormat = 0x15441002; // SDL_PIXELFORMAT_RGBA5551
            break;
        case PixelFormat.RGBA_8888:
            Log.v("SDL", "pixel format RGBA_8888");
            sdlFormat = 0x16462004; // SDL_PIXELFORMAT_RGBA8888
            break;
        case PixelFormat.RGBX_8888:
            Log.v("SDL", "pixel format RGBX_8888");
            sdlFormat = 0x16261804; // SDL_PIXELFORMAT_RGBX8888
            break;
        case PixelFormat.RGB_332:
            Log.v("SDL", "pixel format RGB_332");
            sdlFormat = 0x14110801; // SDL_PIXELFORMAT_RGB332
            break;
        case PixelFormat.RGB_565:
            Log.v("SDL", "pixel format RGB_565");
            sdlFormat = 0x15151002; // SDL_PIXELFORMAT_RGB565
            break;
        case PixelFormat.RGB_888:
            Log.v("SDL", "pixel format RGB_888");
            // Not sure this is right, maybe SDL_PIXELFORMAT_RGB24 instead?
            sdlFormat = 0x16161804; // SDL_PIXELFORMAT_RGB888
            break;
        default:
            Log.v("SDL", "pixel format unknown " + format);
            break;
        }

        mWidth = width;
        mHeight = height;
        int nDeviceWidth = width;
        int nDeviceHeight = height;
        try
        {
            if (Build.VERSION.SDK_INT >= 17) {
                android.util.DisplayMetrics realMetrics = new android.util.DisplayMetrics();
                mDisplay.getRealMetrics( realMetrics );
                nDeviceWidth = realMetrics.widthPixels;
                nDeviceHeight = realMetrics.heightPixels;
            }
        }
        catch ( java.lang.Throwable throwable ) {}

        synchronized(SDLActivity.getContext()) {
            // In case we're waiting on a size change after going fullscreen, send a notification.
            SDLActivity.getContext().notifyAll();
        }

        Log.v("SDL", "Window size: " + width + "x" + height);
        Log.v("SDL", "Device size: " + nDeviceWidth + "x" + nDeviceHeight);
        SDLActivity.onNativeResize(width, height, nDeviceWidth, nDeviceHeight, sdlFormat, mDisplay.getRefreshRate());

        boolean skip = false;
        int requestedOrientation = SDLActivity.mSingleton.getRequestedOrientation();

        if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
        {
            // Accept any
        }
        else if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT)
        {
            if (mWidth > mHeight) {
               skip = true;
            }
        } else if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
            if (mWidth < mHeight) {
               skip = true;
            }
        }

        // Special Patch for Square Resolution: Black Berry Passport
        if (skip) {
           double min = Math.min(mWidth, mHeight);
           double max = Math.max(mWidth, mHeight);

           if (max / min < 1.20) {
              Log.v("SDL", "Don't skip on such aspect-ratio. Could be a square resolution.");
              skip = false;
           }
        }

        if (skip) {
           Log.v("SDL", "Skip .. Surface is not ready.");
           SDLActivity.mIsSurfaceReady = false;
           return;
        }

        /* Surface is ready */
        SDLActivity.mIsSurfaceReady = true;

        /* If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here */
        SDLActivity.onNativeSurfaceChanged();

        SDLActivity.handleNativeState();
    }

I don't know when surfaceChanged(SurfaceHolder holder, int format, int width, int height) is called and where the int format value comes from. The app let SDL do the job. I haven't read the result of Log.v() calls yet, they can be read with the adb logcat command.