SDL freezes on changing & resuming focus

We are using SDL for UI in our application on Android. The application is a bit complex entity altogether & the issue we are facing is that the UI will freeze whenever the application looses focus & is resumed. The UI freezes on either of the below scenarios.

  1. If the settings drop-down is dragged (Just pull down the settings screen from the top).
  2. When the home button is pressed & the application is resumed.
  3. If the application is switched between an another application.
    When the application is resumed back to the previous state, the UI just freezes and becomes unresponsive but other threads in the application will be executing. The only way out is to kill the application.
    Since we ported an application which was using SDL-1.2 we are retaining Window & Surface and have not migrated to Renderers.

We have created a new activity which extends the SDLActivity & to try, I have also overridden the onResume() method in my extended activity.

In the below code segment, I have marked different trials that I performed trying to fix the issue. I have commented them as //Try-1 //Try-2 etc.

I also tried to create a separate thread to handle the events as in the code below.
Also tried to catch events (poll for events) in main thread & tried to render in helper thread, but in that scenario the screen was just blank.

Since our application is complex and uses SDL extensively, I’m sharing a small code snippet which creates the same issue. This is a small application which just displays some colored images one after another with some sleep between the images.

//Passing window to new thread doesn’t work.
static void _pthread_start( int t ) //SDL_Window *window )
{
//Try-1
while(TRUE)
{
SDL_PumpEvents();
}

//Try-2

/* SDL_Event event;
while (1)
{
SDL_PollEvent(&event);
usleep(10);

    switch (event.type)
    {
        //Event handling here...
    }
}*/

//Try-3
// Screen will just be blank, if tried to use window here.

/* SDL_Surface *Bitmap, *B2, *B3, *B4;

B4 = IMG_Load("Green.bmp");
SDL_BlitSurface(B4, NULL, surface, NULL);
SDL_UpdateWindowSurface(window);
sleep(5);

Bitmap = IMG_Load( "Red.bmp" );
SDL_BlitSurface(Bitmap, NULL, surface, NULL);
SDL_UpdateWindowSurface(window);
sleep(5);

B2 = IMG_Load( "Blue.bmp" );
SDL_BlitSurface(B2, NULL, surface, NULL);
SDL_UpdateWindowSurface(window);
sleep(5);

B3 = IMG_Load( "Green.bmp" );
SDL_BlitSurface(B3, NULL, surface, NULL);
SDL_UpdateWindowSurface(window);
sleep(5);*/

}

int main(int argc, char* argv[]) {
SDL_Event event;
SDL_Rect rect;
SDL_Renderer *renderer;
int pressed, nReturnCode;

int t = 0;
int iRC = 0;
pthread_t tThread;           // thread descriptor
pthread_attr_t tAttr;        // thread attributes

/////////////////////////////////////////////////////////////////////////////////////////////////////
nReturnCode = SDL_Init( SDL_INIT_VIDEO );
SDL_LogSetOutputFunction(&sdlLog, (void*)"User Info");
SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE);

SDL_Rect gScreenRect = { 0, 0, 0, 0 };
SDL_DisplayMode displayMode;
if( SDL_GetCurrentDisplayMode( 0, &displayMode ) == 0 )
{
    gScreenRect.w = displayMode.w;
    gScreenRect.h = displayMode.h;
}

window = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 480, 692, SDL_WINDOW_FULLSCREEN);

SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");

surface = SDL_GetWindowSurface(window);

pthread_attr_init( &tAttr );
pthread_attr_setdetachstate( &tAttr, PTHREAD_CREATE_DETACHED );

iRC = pthread_create( &tThread,   // thread id
                             &tAttr,     // thread attributes
                             ( void *( * )( void * ) ) _pthread_start, // thread function
                             ( void * ) &t ); // arguments


boolean quit = FALSE;

while (!quit) {
//Try-4

/* SDL_Event event;
while (SDL_PollEvent(&event)) {
// handle your event here //
//User requests quit
if( event.type == SDL_QUIT )
quit = TRUE;
}/
/
do some other stuff here – draw your app, etc. */

    SDL_Surface *Bitmap, *B2, *B3, *B4;

    B4 = IMG_Load("Green.bmp");
    SDL_BlitSurface(B4, NULL, surface, NULL);
    SDL_UpdateWindowSurface(window);
    sleep(2);

    Bitmap = IMG_Load( "Red.bmp" );
    SDL_BlitSurface(Bitmap, NULL, surface, NULL);
    SDL_UpdateWindowSurface(window);
    sleep(2);

    B2 = IMG_Load( "Blue.bmp" );
    SDL_BlitSurface(B2, NULL, surface, NULL);
    SDL_UpdateWindowSurface(window);
    sleep(2);

    B3 = IMG_Load( "Green.bmp" );
    SDL_BlitSurface(B3, NULL, surface, NULL);
    SDL_UpdateWindowSurface(window);
    sleep(2);

}

//Try-5

/* while (1)
{
SDL_PollEvent(&event);
usleep(10);

    switch (event.type)
    {
        //Event handling here...
    }
}*/

/////////////////////////////////////////////////////////////////////////////////////////////////////
//SDL_DestroyRenderer(renderer);
SDL_UpdateWindowSurface(window);

//SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_SUCCESS;

}

Below is MainActivity.java class file.

package com.test.sdltest;
import android.content.res.AssetManager;
import android.os.Bundle;

import org.libsdl.app.SDLActivity;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class MainActivity extends SDLActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    stringFromJNI();
}

@Override
protected void onResume() {
    super.onResume();
}

/**
 * A native method that is implemented by the 'native-lib' native library,
 * which is packaged with this application.
 */
public native String stringFromJNI();

}

Since I’m also logging the SDL log’s, below are the errors in the SDL log file.

SDL2:[Msg: Window surface is invalid, please call SDL_GetWindowSurface() to get a new surface], [User: User Info], [Prio: 2], [Cat: 1]
SDL2:[Msg: Window surface is invalid, please call SDL_GetWindowSurface() to get a new surface], [User: User Info], [Prio: 2], [Cat: 1]
SDL2:[Msg: Window surface is invalid, please call SDL_GetWindowSurface() to get a new surface], [User: User Info], [Prio: 2], [Cat: 1]

Thanks in advance for any help :smiley: