Нарушение доступа SDL2 нескольких окон

0

Я разрабатываю приложение SDL2, которое должно иметь несколько окон на нескольких мониторах. И я получаю нарушение доступа при рисовании строки с помощью библиотеки SDL_ttf. Я также должен отметить, что приложение открывает окна в отдельных потоках и работает нормально, если не используется SDL_ttf. Я получаю это за исключение при использовании SDL_ttf:

Unhandled exception at 0x0F2BC191 (SDL2.dll) in SDLMultipleWindows.exe: 0xC0000005: Access violation writing location 0x0100000C.

И в этой функции происходит нарушение прав доступа:

bool loadFromRenderedText( std::string textureText, SDL_Color textColor )
{
    SDL_Surface* textSurface = TTF_RenderText_Solid( gFont, textureText.c_str(), textColor );
    SDL_Texture * mTexture = NULL;
    int w, h;
    if( textSurface != NULL )
    {
        mTexture = SDL_CreateTextureFromSurface( renderer, textSurface );
        w = textSurface->w;
        h = textSurface->h;
        SDL_FreeSurface( textSurface );
    }
    else
    {
        printf( "Unable to render text surface! SDL_ttf Error: %s\n", TTF_GetError() );
    }

    SDL_Rect renderQuad = { 250, 300, w, h };
    int result = SDL_RenderCopyEx( renderer, mTexture, NULL, &renderQuad, 0.0, NULL, SDL_FLIP_NONE );
    OutputDebugString(SDL_GetError());
    return true;
}

Исключение происходит на SDL_CreateTextureFromSurface (renderer, textSurface);

Это трассировка стека из Visual studio:

SDL2.dll!SDL_malloc_REAL(unsigned int bytes) Line 4206  C
SDL2.dll!SDL_calloc_REAL(unsigned int n_elements, unsigned int elem_size) Line 4406 C
SDL2.dll!SDL_CreateRGBSurface_REAL(unsigned int flags, int width, int height, int depth, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int Amask) Line 53    C
SDL2.dll!SDL_ConvertSurface_REAL(SDL_Surface * surface, const SDL_PixelFormat * format, unsigned int flags) Line 840    C
SDL2.dll!SDL_CreateTextureFromSurface_REAL(SDL_Renderer * renderer, SDL_Surface * surface) Line 536 C
SDL2.dll!SDL_CreateTextureFromSurface(SDL_Renderer * a, SDL_Surface * b) Line 342   C
SDLMultipleWindows.exe! loadFromRenderedText(std::basic_string<char,std::char_traits<char>,std::allocator<char> > textureText, SDL_Color textColor) Line 162    C++

Я что-то делаю неправильно, или SDL_ttf или SDL2 не могут работать в нескольких потоках?

Есть ли другой способ рисовать строку в SDL2?

Благодарю!

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

Добавление части существующего кода:

ClientWindows::ClientWindows(void)
{
    SDL_Init(SDL_INIT_EVERYTHING);
    IMG_Init(IMG_INIT_PNG);
    TTF_Init();
}

Функция протектора: void ClientWindows :: WindowThread (int i) {AppWindow * rWindow = new AppWindow (i * 1024, 0); Windows.push_back(rWindow); Windows.push_back (rWindow); rWindow->InitScreen(); rWindow-> InitScreen(); } }

Начать графическую функцию:

void ClientWindows::StartGraphics(int number)
{
    for(int i= 0; i<number; i++)
    {
        std::thread* wTread = new std::thread(&ClientWindows::WindowThread,this , i);
        Threads.push_back(wTread);
    }
.
.
.

Окно клиента Конструктор:

AppWindow::AppWindow(int x, int y)
{
    quit = false;
    SCREEN_WIDTH = 1024;
    SCREEN_HEIGHT = 768;
    imagePositionX = 50;
    imagePositionY = 50;
    speed_x = 10;
    speed_y = 10;
    moveX = 10;
    moveY = 10;
    std::ostringstream convert;
    convert << "Graphics";
    convert << x;
    string name = convert.str();

    window = SDL_CreateWindow(name.c_str(), x,
    y, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_BORDERLESS | SDL_WINDOW_OPENGL);
    if (window == nullptr){
        std::cout << SDL_GetError() << std::endl;
    }
    opengl3_context = SDL_GL_CreateContext(window);
    SDL_assert(opengl3_context);
    mt.lock();
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    if (renderer == nullptr){
        std::cout << SDL_GetError() << std::endl;
    }
    mt.unlock();
    background = nullptr,image = nullptr;
    background = SDLLoadImage("../res/Image1024x768.png");
    image = SDLLoadImage("../res/Image1024Classic.png");
    animeImage = SDLLoadImage("../res/32_80x80.png");
    gFont = TTF_OpenFont("../res/sample.ttf", 28);
}

Функция startGraphics окна клиента:

void AppWindow::InitScreen(void)
{
    Clear();
    Render();
    Present();

    //Init fps
    countedFrames = 0;
    fpsTimer.start();

    //For tracking if we want to quit
    Uint32 frameRate = 0;
    while (!quit)
    {
        if (fpsTimer.getTicks() > frameRate + 15)
        {
            frameRate = fpsTimer.getTicks();
            Clear();
            Render();
            Present();
        }
        SDL_Delay(5);
    }
}

Функция, о которой идет речь:

bool AppWindow::loadFromRenderedText(std::string textureText, SDL_Color textColor)
{
    SDL_Surface* textSurface = TTF_RenderText_Solid( gFont, textureText.c_str(), textColor );
    SDL_Texture * mTexture = NULL;
    int w, h;
    if( textSurface != NULL )
    {
        mTexture = SDL_CreateTextureFromSurface( renderer, textSurface );
        w = textSurface->w;
        h = textSurface->h;
        SDL_FreeSurface( textSurface );
    }
    else
    {
        printf( "Unable to render text surface! SDL_ttf Error: %s\n", TTF_GetError() );
    }

    SDL_Rect renderQuad = { 250, 300, w, h };
    int result = SDL_RenderCopyEx( renderer, mTexture, NULL, &renderQuad, 0.0, NULL, SDL_FLIP_NONE );
    OutputDebugString(SDL_GetError());
    return true;
}
Теги:
sdl-2
sdl-ttf

1 ответ

0

Вы не можете использовать функции SDL2 из других потоков, кроме тех, в которых был создан контекст рендеринга, SDL2 не гарантирует безопасность потоков для функций рисования.

Если я правильно помню, единственная поточно-безопасная часть SDL2 - это толкание пользовательских событий в очередь событий.

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

  • 0
    Хорошо, но я создаю новый экземпляр рендерера и окна в каждом потоке. Разве это не делает его частью этой темы?
  • 0
    Вы выполняете CreateSurfaceFromTexture в том же потоке, в котором вы создали средство визуализации?
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню