Почему SDL зависает при смене и возобновлении фокуса? - PullRequest
2 голосов
/ 10 мая 2019

Мы используем SDL-2.0.8 для пользовательского интерфейса в нашем приложении на Android.Приложение представляет собой довольно сложную сущность, и проблема, с которой мы сталкиваемся, заключается в том, что пользовательский интерфейс будет зависать всякий раз, когда приложение теряет фокус и возобновляется.Пользовательский интерфейс зависает в любом из следующих сценариев.

  1. Если перетащить раскрывающийся список настроек (просто потяните экран настроек сверху).
  2. Когда кнопка «Домой»нажата и приложение возобновляется.
  3. Если приложение переключается между другим приложением.

Когда приложение возвращается в предыдущее состояние, пользовательский интерфейс просто зависает и перестает отвечать на запросы.но другие потоки в приложении будут выполняться.Единственный выход - убить приложение.Так как мы портировали приложение, которое использовало SDL-1.2, мы сохраняем Window & Surface и не мигрировали в Renderer.

Мы создали новое действие, которое расширяет SDLActivity и, чтобы попробовать, я также переопределил onResume() метод в моей расширенной деятельности.Удивительно, но точка останова в onResume () достигается только при запуске приложения, а не при его возобновлении.

Я прошел по ссылкам ниже и попробовал то, что они предложили, но безуспешно.

Программа SDL зависает

SDL: окно зависает

В приведенном ниже фрагменте кода я отметил различные испытания, которые я выполнил, пытаясьчтобы исправить проблему.Я прокомментировал их как // 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();
}

Так как я 'm также регистрирует журналы SDL, ниже приведены ошибки в файле журнала SDL.

* SDL2: [Msg: поверхность окна недопустима, пожалуйста, вызовите SDL_GetWindowSurface (), чтобы получить новую поверхность], [Пользователь: ПользовательInfo], [Prio: 2], [Cat: 1]

SDL2: [Msg: поверхность окна недействительна, пожалуйста, вызовите SDL_GetWindowSurface (), чтобы получить новую поверхность], [Пользователь: Информация о пользователе], [Prio: 2], [Cat: 1]

SDL2: [Msg: недопустимая поверхность окна, пожалуйста, вызовите SDL_GetWindowSurface (), чтобы получить новую поверхность], [Пользователь: Информация о пользователе], [Prio: 2], [Cat: 1] *

Заранее спасибо за любую помощь:)

1 Ответ

0 голосов
/ 14 июля 2019

Просто обновление для всех, кто наткнулся на этот пост. После нескольких недель борьбы мы просто поняли, что нам нужно использовать Renderer вместо Surface, чтобы решить проблему зависания пользовательского интерфейса. Приведенный выше пример программы не будет зависать после потери фокуса и возобновления при использовании рендерера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...