SDL_PollEvent freezes on alt-tab

"lemmn" <[email protected]>
Newsgroups gmane.comp.lib.sdl
Message-ID <[email protected]>
I am using Windows 10 and visual studio 2015, and SDL 2.0.4.

I believe this is a minimal repro case.. I had to cut out a lot of code to get down to this, so I'm sorry if there is extra code here.

This program just draws a square on the screen and then should quit when you press the space bar.

Repro steps:
- run the program
- press alt-tab while the game is running
- notice the game program locking up

The bug happens when I hit alt-tab.  If I do that, then the game becomes locked up at the call to PeekMessage() inside of WIN_PumpEvents(), with this callstack if I break:


Code:

 	[External Code]	
>	SDL2.dll!WIN_PumpEvents(SDL_VideoDevice * _this) Line 977	C
 	SDL2.dll!SDL_PumpEvents_REAL() Line 405	C
 	SDL2.dll!SDL_WaitEventTimeout_REAL(SDL_Event * event, int timeout) Line 437	C
 	SDL2.dll!SDL_PollEvent_REAL(SDL_Event * event) Line 419	C
 	SDL2.dll!SDL_PollEvent(SDL_Event * a) Line 157	C
 	MyMusic.exe!SDL_main(int argc, char * * argv) Line 154	C++
 	MyMusic.exe!main_utf8(int argc, char * * argv) Line 127	C
 	MyMusic.exe!WinMain(HINSTANCE__ * hInst, HINSTANCE__ * hPrev, char * szCmdLine, int sw) Line 191	C
 	[External Code]	




And the render thread is running happily.

This bug only happens in full screen.  If I remove this code:

flags |= SDL_WINDOW_FULLSCREEN;

then the game runs fine, and I do not get any freeze on using alt-tab.


I have a feeling that the render thread might be the problem, but I must be able to render in a separate thread for this game.  I followed this guide and everything seems to be working fine, apart from this freeze
https://github.com/vheuken/SDL-Render-Thread-Example/blob/master/main.cpp



Code:

#include "stdafx.h"

#include <vector>
#include <map>
#include <fstream>
#include <memory>
#include <limits>
#include <iomanip>
#include <thread>

#include <Windows.h>

#include <SDL.h>



// singleton to hold a bunch of global game state stuff
class Game
{
public:
	Game()
	{}

	SDL_Rect m_windowedRect;

	void SetUpScreen();
	void TearDownScreen();

	void StartRenderer();
	void KillRenderer();


	static Game& Get();

	// window and screen
	SDL_Window* m_Window;
	SDL_GLContext m_Context;


	bool m_QuitGame;

	SDL_Renderer* m_Renderer = nullptr;
	std::thread* m_RenderThread = nullptr;
};



static Game g_Game;
Game& Game::Get()
{
	return g_Game;
}

void Game::SetUpScreen()
{
	// make a sane default window position and size
	if ( 0 == SDL_GetDisplayBounds( 0, &m_windowedRect ) )
	{
		m_windowedRect.x = m_windowedRect.w * 0.05f;
		m_windowedRect.y = m_windowedRect.h * 0.05f;
		m_windowedRect.w = m_windowedRect.w * 0.9f;
		m_windowedRect.h = m_windowedRect.h * 0.9f;
	}
	else
	{
		m_windowedRect = { 10, 10, 1024, 768 };
	}

	int32_t flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE;

	flags |= SDL_WINDOW_FULLSCREEN;

	SDL_Rect resolution;
	resolution = m_windowedRect;

	m_Window = SDL_CreateWindow( "hi friend", resolution.x, resolution.y, resolution.w, resolution.h, flags );
}

void Game::TearDownScreen()
{
	SDL_DestroyWindow( m_Window );
	m_Window = NULL;
}

void RenderThread();

void Game::StartRenderer()
{
	m_RenderThread = new std::thread( RenderThread );
}

static bool stopRenderer;

void Game::KillRenderer()
{
	stopRenderer = true;
	m_RenderThread->join();

	delete m_RenderThread;
	m_RenderThread = nullptr;
}

void RenderThread()
{
	SDL_GL_MakeCurrent( g_Game.m_Window, g_Game.m_Context ); // not sure what this does - it was happening in the example

	g_Game.m_Renderer = SDL_CreateRenderer( g_Game.m_Window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC );
	SDL_SetRenderDrawBlendMode( g_Game.m_Renderer, SDL_BLENDMODE_BLEND );

	while( 1 )
	{
		if ( stopRenderer )
		{
			goto quit;
		}

		SDL_Rect rect{ 10, 10, 10, 10 };
		SDL_SetRenderDrawColor( g_Game.m_Renderer, 0xff, 0xff, 0xff, 0xff );
		SDL_RenderFillRect( g_Game.m_Renderer, &rect );
		SDL_RenderPresent( g_Game.m_Renderer );
	}

quit:
	// shut down
	SDL_DestroyRenderer( g_Game.m_Renderer );
	g_Game.m_Renderer = NULL;
}

int main( int argc, char* argv[] )
{

	SDL_Init( SDL_INIT_AUDIO | SDL_INIT_VIDEO );

	SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "linear" );

	g_Game.SetUpScreen();


	// not entirely sure this is needed but it was happening before creating the render thread in example
	g_Game.m_Context = SDL_GL_GetCurrentContext();
	SDL_GL_MakeCurrent( g_Game.m_Window, nullptr );

	g_Game.StartRenderer();

	// main loopy thing
	while ( 1 )
	{
		if ( g_Game.m_QuitGame )
		{
			break;
		}

		SDL_Event e;
		while ( SDL_PollEvent( &e ) )
		{
			if ( e.type == SDL_KEYDOWN )
			{
				if ( e.key.keysym.sym == SDLK_SPACE )
				{
					g_Game.m_QuitGame = true;
				}
			}
		}

		Sleep( 10 );
	}

	g_Game.KillRenderer();

	g_Game.TearDownScreen();

	SDL_Quit();
	return 0;
}

_______________________________________________
SDL mailing list
[email protected]
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.