SDL为什么冻结在更改和恢复焦点上?

时间:2019-05-10 15:03:44

标签: android-ndk sdl-2

我们在Android上的应用程序中将SDL-2.0.8用于UI。该应用程序完全是一个复杂的实体,我们面临的问题是,只要应用程序失去焦点并恢复,UI就会冻结。用户界面在以下两种情况下均会冻结。

  1. 如果拖动设置下拉菜单(只需从顶部下拉设置屏幕)。
  2. 按下主页按钮并恢复应用程序。
  3. 如果该应用程序在另一个应用程序之间切换。

当应用程序恢复到以前的状态时,UI只会冻结并且变得无响应,但是应用程序中的其他线程将在执行。唯一的出路是杀死应用程序。 由于我们移植了使用SDL-1.2的应用程序,因此我们保留了Window&Surface,并且尚未迁移到Renderer。

我们创建了一个新的活动,该活动扩展了SDLActivity,并尝试进行扩展,我还重写了onResume()方法。令人惊讶的是,仅在应用程序启动时才在onResume()处找到断点,而在恢复应用程序时则没有。

我浏览了以下链接并尝试了他们的建议,但没有成功。

SDL program freezes

SDL: Window freezes

在下面的代码段中,我标记了为解决该问题而执行的其他试验。我已将它们评论为// Try-1 // Try-2等。

我还尝试创建一个单独的线程来处理事件,如下面的代码所示。 还尝试在主线程中捕获事件(对事件进行轮询)并尝试在辅助线程中呈现,但是在这种情况下,屏幕只是空白。

由于我们的应用程序很复杂并且广泛使用SDL,因此我共享一个小的代码段,这会造成同样的问题。这是一个很小的应用程序,它仅一个接一个地显示一些彩色图像,并且图像之间会休眠。

//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;
}

下面是MainActivity.java类文件。

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();
}

由于我也在记录SDL日志,因此以下是SDL日志文件中的错误。

* SDL2:[消息:窗口表面无效,请调用SDL_GetWindowSurface()以获取新表面],[用户:用户信息],[优先级:2],[猫:1]

SDL2:[消息:窗口表面无效,请调用SDL_GetWindowSurface()以获取新表面],[用户:用户信息],[优先级:2],[猫:1]

SDL2:[消息:窗口表面无效,请调用SDL_GetWindowSurface()以获取新表面],[用户:用户信息],[优先级:2],[猫:1] *

在此先感谢您的帮助:)

1 个答案:

答案 0 :(得分:0)

对于那些偶然发现此帖子的人来说只是一个更新。 经过数周的努力,我们才发现必须使用Renderer而不是Surface来解决UI Freeze问题。失去焦点并使用Renderer进行恢复后,上面的示例程序将不会冻结。