Why does SDL freezes on changing & resuming focus?

牧云@^-^@ 提交于 2020-01-15 07:24:13

问题


We are using SDL-2.0.8 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 the application which was using SDL-1.2 we are retaining Window & Surface and have not migrated to Renderer's.

We have created a new activity which extends the SDLActivity & to try, I have also overridden the onResume() method in my extended activity. Surprisingly the break-point at the onResume( ) is hit only when the application starts & not when the application is resumed.

I have gone through the below links & tried what they have suggested but no success.

SDL program freezes

SDL: Window freezes

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 :)


回答1:


Just an update for anyone who stumbles upon this post. After struggling for couple of weeks we just figured out that we have to use Renderer's instead of Surface's to solve the UI Freeze issue. The sample program above will not freeze after loosing focus and resuming when Renderer's are used.



来源:https://stackoverflow.com/questions/56080259/why-does-sdl-freezes-on-changing-resuming-focus

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!