SDL2 resizing window destroys textures

Found quite a lot of posts regarding this and I thought this issue was a few years old already.

I am having to drop all renderers and textures and recreate them after each window resize.

Platform is Windows 10 MINGW. I assume directx as hinting to the renderer with “opengl” fails.

Has this issue been addressed?

That should not happen normally as far as I can tell. Need a bit more info from you though. For starters: what version of SDL are you using? Can you boil down your code, (the smaller, the better) to something we can take a look at where it crashes? What error message are you getting; or what happens after you resize your window?

Version 2.08

The problem I am having is my emulation rendering loop is running in a different thread to the SDL main loop where the I process the SDL events. The rendering loop is continually accessing the texture area during the screen resize and doesn’t know the texture is defunct and so while I’m trying to recreate the new texture in the event callback the rendering loop segmentation faults.

And since I don’t know when a resize can occur I don’t know when to halt the rendering loop in advance!

There’s your problem. Only the thread that called SDL_InitSubSystem(SDL_INIT_VIDEO) can actually make changes like that. I have a video thread that is separate from my main loop, as well as a event callback function, so I know it can be done. I use a queue container surrounded by mutex locks to tell my video thread when to make changes. If you have a flag or something that can store information about the new screen size request, that should probably work as well.

What do you mean by; Make changes like that?

At the moment all SDL calls are made from the main thread.

The main thread prepares all windows, surfaces textures and establishes locks and handles all events. The main thread passes the pixel area pointer obtained from the SDL_LockTexture to the rendering thread which triggers the rendering thread to render. The rendering thread when complete singles the main thread to unlock the texture and perform the RenderPresent. So the rendering thread works only with a memory pointer. However once started the rendering thread must complete the entire render without having the rug pulled out from under its feet while processing. This is how the directx code works as well. In fact both the directx and SDL rendering code are identical (not one line different). They just have different memory pointers and I can watch the directx and SDL window running side by side in the emulation (for comparison testing). Once it all works I will remove the directx code!

So at the moment with just 100+ lines of code everything works in the emulation except resizing.

An issue for me is I am converting inherited code that I am converting from directx to SDL. Currently I have made the conversion of a 20+ K line code base by changing 100 lines of directx code to SDL. The multi thread issue is not an issue in directx because the textures do not die on a window resize. So to support resizing in SDL from changing just 100 lines of code I’m going to have to rewrite most of the emulation, obviously I want to avoid that or my other solution is simply not to provide resizing as an option in the SDL version!

And hence why I have come here to ask for any suggestion that anyone may have.

I’m considering adding a mutex or flag to the rendering code that it will be forced to check before every pixel manipulation but I consider this an expense solution!

Any other ideas welcome!

Sorry about that, admittedly I have problems communicating. By my understanding, basically most graphical operations should only be done in the thread that called SDL_InitSubSystem(SDL_INIT_VIDEO). Only that thread should be doing any changes to the windows, (resizing, fullscreen, windowed, and whatnot). From the Wiki: NOTE: You should not expect to be able to create a window, render, or receive events on any thread other than the main one. You can still use a separate thread, but there’s no guarantee that it will work.

If you’re using OpenGL, you might be able to give the context to a different thread, but you’d have to give it back and forth each time you resize the window. OpenGL context is bound to a thread; you cannot call OpenGL operations from another thread. With other words, all OpenGL operations on a single context have to be called from the same thread that used to make the context current (with wglMakeCurrent) Do keep in mind that SDL will spam you with window resize events while dragging the window, (it does for me), and a large number of resize calls can slow your program to a crawl if your passing the context back and forth.

In my program, I just enabled my window to be resizeable, and I don’t have any logic to do anything with a window resize. Don’t have anything but simple lines following the mouse right now, but it doesn’t crash. I know some emulators have options like “stretch to fill” the window and things like that. So maybe instead of having hard numbers in the video logic, have it calculate the drawing based on the windows current size?

If anything, try ignoring the resize events and see if it still crashes. From my little experiment above, there’s no reason to call SDL_SetWindowSize after a resize event. I could be wrong, but those events are so that you’re aware of the changes so you can resize anything that needs to be adjusted.

Thanks for reply.

Tried ignoring the resize events and the window freezes on the last frame drawn. I can see via the debugger the renderer is still drawing and there is no segmentation fault but nothing updates when RenderPresent is called.

And yes I have set the render to automatically scale using SDL_RenderSetLogicalSize. I have tested this is a small test app and this appears to work. However the test app doesn’t keep locking the texture to do its work, it just loads a couple of static images.

I will play around with the test app and see if I can recreate the problem!

Good news and bad news.

The good news I figured out the segmentation faults occurring in the renderer thread had nothing to do with timing. The real problem was the renderer was being passed the Pitch of the Window Surface. This worked fine when the surface and texture were the same size but cause the renderer to access outside the bounds of the texture memory returned by SDl_LockTexture when the surface was larger than the texture.

Second good news. (In case you are not up to speed. My texture has a logical size set to 640x480 to facilitate SDL automatic scaling.) When the main app receives the event to become full screen everything works as expected and the emulation continues running at full screen (correctly scaled).

The bad news. When the main app receives the event to become windowed the window reverts back to its previous size but further calls to RenderPresent do not do anything. I’m using the same routine to recreate the textures on both occasions so I’m not sure whats happening. I have checked the pitch!

However the renderer is convinced it is actually drawing and for several seconds at 60 frames a second everything continues normally (but without any output) but then SDL_RenderCopy begins to return the error : “Reset. Required.”

Edited correction error: “Reset(): INVALIDCALL”

Not sure what that means!

Anyway I will keep looking at my recreate texture routine for now!

This surface will be invalidated if the window is resized. After resizing a window this function must be called again to return a valid surface. Just now found that out. Maybe give that a whirl when SDL_RenderCopy requires a reset?

This surface will be invalidated if the window is resized. After resizing a window this function must be called again to return a valid surface.

Which Function??? SDL_GetWindowSurface!!!

OK!!!

All fixed!!!

Problem turned out to be a stray SDL call that wasn’t in the main thread. Why its was working at all is a mystery!

Placed SDL call in main thread and everything is working!

Congratulations, good to hear.