SDL2 Нарушение доступа нескольких окон
Я занимаюсь разработкой приложения 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); 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);
}
Функция запуска клиентской части окна:
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;
}
1 ответ
Вы не можете использовать функции SDL2 из других потоков, отличных от того, в котором был создан контекст рендеринга. SDL2 не гарантирует никакой безопасности потоков для функций рисования.
Если я правильно помню, единственная поточно-безопасная часть SDL2 - это отправка пользовательских событий в очередь событий.
Поэтому я предполагаю, что AccessViolation происходит потому, что вы пытаетесь использовать контекст визуализации из другого потока, а не из того, в котором он был создан.