SDL2 Create Texture from different thread on OSX

I’m trying to load textures for an SDL2 program in a separate thread for a loading screen. My code looks something like this

Code:

int batchLoad(void *ptr) {
loop through resources
SDL_LockMutex(renderMutex);

    SDL_Texture *texture = NULL;

SDL_Surface *surface = IMG_Load(("../resources/" + fileName).c_str());
if (surface) {
texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_FreeSurface(surface);
}
SDL_UnlockMutex(renderMutex);

    // store texture

return 0;
}

void LoadingScreen::loadResources() {
// do some stuff

renderMutex = SDL_CreateMutex();

ScreenMap screenMap;
// init with data
SDL_Thread* load = SDL_CreateThread(batchLoad, “batchLoad”, &screenMap);

while loading {
// do work

SDL_LockMutex(renderMutex);

SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, white, NULL, NULL);

// draw stuff

SDL_RenderPresent(renderer);
SDL_UnlockMutex(renderMutex);

}

SDL_WaitThread(load, NULL);
SDL_DestroyMutex(renderMutex);
SDL_DestroyMutex(satMutex);

On Windows this works perfectly fine, but on OSX I get an error at the CreateTextureFromSurface call. It segfaults with a null pointer error. Here’s the osx problem report.

Code:

Thread 10 Crashed:: batchLoad
0 libGL.dylib 0x00007fff885ead32 glGenTextures + 18

Thread 10 crashed with X86 Thread State (64-bit):
rax: 0x0000000000000000 rbx: 0x00007ff913c37ad0 rcx: 0x0000000000000001 rdx: 0x00007ff913c37b50
rdi: 0x0000000000000001 rsi: 0x00007ff913c37b50 rbp: 0x00000001157ae4d0 rsp: 0x00000001157ae4d0
r8: 0x0000000000000004 r9: 0x00007ff913c00000 r10: 0x0000000023f4e094 r11: 0x000000000abea012
r12: 0x00007ff913d1e3b0 r13: 0x00007ff913d1e3b0 r14: 0x000000000000001a r15: 0x0000000000000022
rip: 0x00007fff885ead32 rfl: 0x0000000000010246 cr2: 0x0000000000000000

and lldb

Code:

  • thread #9: tid = 0xee08, 0x00007fff885ead32 libGL.dylibglGenTextures + 18, name = 'batchLoad', stop reason = EXC_BAD_ACCESS (code=1, address=0x0) frame #0: 0x00007fff885ead32 libGL.dylibglGenTextures + 18
    libGL.dylib`glGenTextures + 18:
    -> 0x7fff885ead32: movq (%rax), %rdi
    0x7fff885ead35: movq 0x318(%rax), %rax
    0x7fff885ead3c: movl %ecx, %esi
    0x7fff885ead3e: popq %rbp

when I comment out all the thread stuff and just call batch load normally, there are no errors so I figured there has to be some concurrency issue. But I’m using a mutex for all of the renderer calls so I’m not sure what the issue could be. And then I also don’t know why it would work fine on Windows but not on OSX

All SDL_Render functionality (including SDL_CreateTexture) can only be used from the main thread - the SDL_render.h header file as well as https://wiki.libsdl.org/CategoryRender mention this.On May 3, 2014, at 2:40 AM, programmingmind wrote:

I’m trying to load textures for an SDL2 program in a separate thread for a loading screen.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

The workaround I’m using is to load all texture files into surfaces in the loading thread, then later convert them into textures on the rendering thread. Seems counter-intuitive but it works on Linux. I haven’t tried on OSX so I don’t know if it works on the platform or not.