SDL_UpdateWindowSurface() не обновляется после SDL_FillRect()

Я учусь создавать свое первое окно, следуя руководству LazyFoo, все компилируется и выполняется, но поверхность не обновляется при вызове SDL_UpdateWindowSurface(), как показано на рисунке ниже:

Поверхность должна была быть белой

Как видите, последнее, что появляется, это мой фон. Я уже тестирую эту программу на своем другом ноутбуке, и все работает нормально, и я использую ту же систему, обе обновлены.

Мой код:

#include <SDL2/SDL.h>

const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

int main(){
    SDL_Window* window = NULL;
    SDL_Surface* screenSurface = NULL;
    if(SDL_Init(SDL_INIT_VIDEO) < 0){
        printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
    }else{
        window = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
        if(window == NULL){
            printf("Window could not be created SDL_Error: %s\n", SDL_GetError() );
        }
        else{
            screenSurface = SDL_GetWindowSurface(window);
            if(screenSurface == NULL){
                printf("Surface could not be loaded SDL_Error: %s\n", SDL_GetError());
            }else{
                SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 255, 255, 255));
                SDL_UpdateWindowSurface(window);
                SDL_Delay(3000);
            }
        }
    }
}

Странная вещь: если я добавлю SDL_Delay(1000) перед SDL_UpdateWindowSurface(), через 1 секунду я смогу увидеть поверхность, заполненную белым, но это не кажется правильным решением, так как программа отлично работает на моем ноутбуке.

Редактировать 1:

Просто поймите одну вещь: среда моего рабочего стола, в которой я разрабатываю эту программу, использует в качестве оконного менеджера awesomewm. Мой ноутбук использует gnome как DE. Я только что установил gnome на свой рабочий стол и вуаля, программа работает как положено. Теперь мне просто интересно, почему это происходит. Скриншот той же программы, работающей в Gnome:

Работает как положено(Поверхность заполнена белым цветом)

Редактировать 2:

Как упоминал keltar, SDL обновлял поверхность до того, как мой оконный менеджер загрузил их. Решение состоит в том, чтобы обработать событие окна EXPOSED, когда окно загружается оконным менеджером.

SDL_Event event;

while(SDL_WaitEvent(&event))){
    switch(event.type){
        case SDL_WINDOWEVENT:
            switch(event.window.event){
                case SDL_WINDOWEVENT_EXPOSED:
                    SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 255, 255, 255));
                    SDL_UpdateWindowSurface(window);
                    SDL_Delay(3000);
                    SDL_Quit();
                    break;
            }
    }
}

person Yuri Santos    schedule 14.11.2017    source источник
comment
Учебник неверен, вы не можете нарисовать один раз и ожидать, что результат останется навсегда (или вообще когда-либо). Это верно для любой графической программы, но инструменты GUI обычно перерисовываются, когда это необходимо. Инструментарий, ориентированный на игры, обеспечивает более точное управление; наиболее распространенным подходом является безусловное перерисовывание время от времени (например, каждый интервал вертикальной синхронизации), или, если известно, что изображение в основном статично и вас беспокоит загрузка ЦП/ГП, перерисовывать, когда оконная система попросит вас об этом с соответствующим событие   -  person keltar    schedule 15.11.2017
comment
@keltar, значит, все, что мне нужно сделать, это перерисовать, когда происходят эти события?   -  person Yuri Santos    schedule 15.11.2017
comment
Думаю, перерисовать на мероприятии EXPOSED. Оконный менеджер может показать ваше окно чуть позже => вы рисовали, пока оно не было видно, теперь его видимость изменилась (то ли было скрыто, то ли затенено другим окном) - вот и происходит событие экспонирования, перерисовка. Затените ваше окно другой программой, снова переключитесь на свое - теперь область, которая не была видна, нужно перерисовать. С составными оконными менеджерами (например, беспорядком в gnome3) все обстоит иначе, но ни в коем случае не яснее — они теоретически могут показывать старое изображение, если вы не перерисовываете (например, для более плавного движения окна), но я не думаю, что они необходимы для .   -  person keltar    schedule 16.11.2017
comment
@keltar понял! Спасибо за объяснение. Теперь я понимаю, что происходило.   -  person Yuri Santos    schedule 17.11.2017
comment
У меня была такая же проблема с KDE/KWin. Загвоздка в том, что по умолчанию SDL пытается обойти компоновщик, что делает SDL_UpdateWindow неэффективным. Но когда вы добавляете подсказку SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR,·"0"); непосредственно перед SDL_Init(), компоновщик остается и UpdateWindow работает. Я до сих пор не знаю, почему вам не нужно ждать события EXPOSED с включенным композитором.   -  person JonnyRobbie    schedule 26.05.2020
comment
Ответ на этот вопрос может быть таким: «Похоже, что sdl pollevent предотвращает обновление поверхности окна»> stackoverflow.com/questions/40113594/ -> т. е. поверхность становится недействительной при некоторых событиях оконного менеджера, таких как EXPOSED   -  person Dalibor Filus    schedule 10.03.2021