SDL2访问违反多个窗口

时间:2014-02-24 11:54:30

标签: c++ sdl-2 sdl-ttf

我正在开发SDL2应用程序,它需要在多个监视器上有多个窗口。我在使用SDL_ttf库绘制字符串时遇到访问冲突。我还应该提到Application正在单独的线程中打开窗口,并且如果没有使用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(渲染器,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-&GT; 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;
}

1 个答案:

答案 0 :(得分:0)

除了创建渲染上下文之外的其他线程,您不能使用SDL2函数,SDL2保证绘图函数没有线程安全。

如果我没记错的话,SDL2唯一的线程安全部分就是将自定义事件推送到事件队列。

所以我猜测会出现 AccessViolation ,因为你试图使用来自另一个线程的渲染上下文而不是创建它的那个。