SDL2 в Arch Linux: окно отображает то, что находится за ним на экране

Я только начал с SDL2, прочитал пару статей об этом и смог успешно скомпилировать тестовую программу, которую я написал для Arch Linux. Единственная проблема, которая кажется возникшей, заключается в том, что создаваемое окно не отображает изображение. Я пробовал запустить тот же код на Mac, что привело к ожидаемому результату. Я использую CLion, который не является злоумышленником, потому что компиляция с g ++ через CLI приводит к тому же результату.

Моя установка Arch Linux:

OS: Arch Linux x86_64
Kernel Release: 4.6.2-1-ARCH

Вот код, который я компилирую:

#include <iomanip>
#include <SDL2/SDL.h>
using namespace std;

const int WIDTH = 640;
const int HEIGHT = 480;

bool init();
bool loadMedia();
int close();

SDL_Window* window = NULL;
SDL_Surface* surface = NULL;
SDL_Surface* image = NULL;

int main(int argc, char** argv) {
    if(init())
        if(loadMedia())
            printf("Media loaded");
    SDL_BlitSurface(image, NULL, surface, NULL);
    SDL_UpdateWindowSurface(window);
    SDL_Delay(5000);
    return close();
}

bool init() {
    if(SDL_Init(SDL_INIT_EVERYTHING) < 0) {
        printf("Error initializing SDL: %s", SDL_GetError());
        return false;
    } else {
        window = SDL_CreateWindow("Hello World", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
        if(window == NULL) {
            printf("Error creating window: %s", SDL_GetError());
            return false;
        }
        else
            surface = SDL_GetWindowSurface(window);
    }
    return true;
}

bool loadMedia() {
    image = SDL_LoadBMP("/home/me/ClionProjects/SDLTest/test.bmp");
    if(image == NULL) {
        printf("Error loading in image: %s", SDL_GetError());
        return false;
    }
    return true;
}

int close() {
    SDL_FreeSurface(surface);
    SDL_FreeSurface(image);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}

Мой файл CMakeLists.txt (используется CLion):

cmake_minimum_required(VERSION 3.5)
project(SDLTest)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -w -lSDL2")

set(SOURCE_FILES main.cpp)
add_executable(SDLTest ${SOURCE_FILES})

И команда Unix, которую я использовал для компиляции с g ++:

g++ main.cpp -w -lSDL2 -o prog

Как это выглядит при запуске кода на Arch:

Код работает в Arch Linux

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

На Mac:

введите здесь описание изображения

Нашел пару статей, также намекающих на эту проблему, но решения этих статей не работают для меня. Конкретно я про эти статьи.

SDL - в окне ничего не отображается

https://bbs.archlinux.org/viewtopic.php?id=188412

https://gamedev.stackexchange.com/questions/117792/why-does-sdl-render-the-background-from-the-operating-system-to-the-window

Надеюсь, что я предоставил достаточно информации, и что есть кто-то, кто столкнулся с той же проблемой и смог ее решить. Заранее спасибо!


Редактировать после комментарий keltar (все еще не выполняющий то, что должен):

#include <iomanip>
#include <SDL2/SDL.h>
using namespace std;

const int WIDTH = 640;
const int HEIGHT = 480;

bool init();
bool loadMedia();
//int close();

SDL_Window* window = NULL;
SDL_Surface* surface = NULL;
SDL_Surface* image = NULL;

int main(int argc, char** argv) {
    if(init())
        if(loadMedia())
            printf("Media loaded");
    SDL_BlitSurface(image, NULL, surface, NULL);
    SDL_UpdateWindowSurface(window);
    SDL_Delay(5000);
    SDL_Quit();
    return 0;
}

bool init() {
    if(SDL_Init(SDL_INIT_EVERYTHING) < 0) {
        printf("Error initializing SDL: %s", SDL_GetError());
        return false;
    } else {
        window = SDL_CreateWindow("Hello World", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
        if(window == NULL) {
            printf("Error creating window: %s", SDL_GetError());
            return false;
        }
        else
            surface = SDL_GetWindowSurface(window);
    }
    return true;
}

bool loadMedia() {
    image = SDL_LoadBMP("/home/me/ClionProjects/SDLTest/test.bmp");
    if(image == NULL) {
        printf("Error loading in image: %s", SDL_GetError());
        return false;
    }
    return true;
}

//int close() {
//    SDL_FreeSurface(surface);
//    SDL_FreeSurface(image);
//    SDL_DestroyWindow(window);
//    SDL_Quit();
//    return 0;
//}

person 7z.    schedule 29.06.2016    source источник
comment
1. не освобождайте поверхность окна и 2. - в большинстве случаев (обычно с задействованным оконным менеджером композитинга) вы не можете ожидать появления изображения, просто ожидая. Добавьте цикл, который очищает очередь событий, затем рисует ваше изображение, а затем повторяет.   -  person keltar    schedule 30.06.2016
comment
... и я снова забыл о функции close. Пожалуйста, не делай этого. stackoverflow.com/questions/31482117/   -  person keltar    schedule 30.06.2016
comment
Спасибо за советы, я рассмотрю их, когда буду более свободно разбираться в фреймворке. На данный момент я просто следую этому руководству, как вы, возможно, уже заметили: lazyfoo. net / tutorials / SDL / 02_getting_an_image_on_the_screen / Изменение того, что вы предложили, не повлияло на тот факт, что на самом деле ничего не отображается из того, о чем я прошу. Главное, что я сейчас пытаюсь сделать, это исправить несоответствие, которое, кажется, существует между запуском этого кода в Arch Linux и его запуском в OS X.   -  person 7z.    schedule 30.06.2016
comment
Какой у вас текущий код? Пожалуйста, добавьте это к вопросу.   -  person keltar    schedule 30.06.2016
comment
Добавил код к моему вопросу. Я еще ничего не сделал с очередями событий, поэтому мне не удалось воспроизвести эту часть предложения. Как вы думаете, в этом вина? Если да, то как же он работает без явных ошибок в OS X?   -  person 7z.    schedule 30.06.2016
comment
Почти уверен, что это так (это не первый вопрос с этой проблемой здесь). Я не могу описать причины этого (и обходные пути) в коротком комментарии, вероятно, позже опубликую лучшее описание, если не будет другого ответа. Краткая версия - это просто так получилось, на этот счет нет никаких гарантий. Для правильного отображения вы должны соответствующим образом реагировать на события окна - например, перерисовать, когда оконный менеджер попросит вас об этом.   -  person keltar    schedule 30.06.2016


Ответы (1)


Я без проблем запустил ваш код на Ubuntu 14.04. Чтобы проверить, не является ли проблема «драйвером рендеринга» в Linux, не могли бы вы запустить мою маленькую игру под GPL из командной строки и скопируйте и вставьте информацию, отображаемую в консоли?

Вы должны увидеть что-то вроде этого:

Video drivers (2): 'x11' 'dummy', active = 'x11'
Screen: 1920 x 1080, game: 1024 x 576
Rendering drivers (2): 'opengl' 'software', active = 'opengl'
Render flags = 0x000a | ACCELERATED | TARGETTEXTURE
Window flags = 0x001a | OPENGL | BORDERLESS
0 joystick(s) detected

Я столкнулся с такой же проблемой в CentOS 5, когда флаг «SDL_RENDERER_PRESENTVSYNC» установлен в рендерере или пока вы не копируете текстуру в рендерер.

Другая идея, что происходит, когда вы это делаете?

for(int i = 0; i < 10; i++) {
    SDL_BlitSurface(image, NULL, surface, NULL);
    SDL_UpdateWindowSurface(window);
    SDL_Delay(500);
}
person Joseph Paul    schedule 01.07.2016
comment
Спасибо за ответ! Когда я помещаю функцию рендеринга изображения в цикл, вторая итерация вокруг нее фактически отображает изображение. Поскольку я планирую создать игру, которая должна отображаться непрерывно, я не вижу проблем в использовании Arch в качестве платформы разработки (которая является моей предпочтительной ОС). По-прежнему странно, что первый вызов для рендеринга приводит к копированию содержимого на экране за окном. И дело не только в рендеринге изображения. Попытка окрасить фон в красный цвет с помощью прямоугольника дает то же самое. - person 7z.; 01.07.2016
comment
Если вы планируете создавать игру, конечно, вам не следует использовать SDL_UpdateWindowSurface (), который рендерится «программно», но 2D ускорен. Функции рендеринга или OpenGL. - person Joseph Paul; 01.07.2016