The SDL forums have moved to discourse.libsdl.org.
This is just a read-only archive of the previous forums, to keep old links working.


SDL Forum Index
SDL
Simple Directmedia Layer Forums
SDL_PollEvent freezes on alt-tab
lemmn


Joined: 18 Jun 2016
Posts: 5
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;
}

lemmn


Joined: 18 Jun 2016
Posts: 5
Heres a slightly simpler repro:

Code:

#include "stdafx.h"

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

#include <Windows.h>

#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>

#include "MyMusic.h"


bool quitGame;


// window and screen
SDL_Window* m_Window;
SDL_GLContext m_Context;
SDL_Renderer* m_Renderer = nullptr;
std::thread* m_RenderThread = nullptr;


static bool stopRenderer;

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

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

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

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

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

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

   TTF_Init();


   SDL_Init( SDL_INIT_AUDIO | SDL_INIT_VIDEO );

   SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "linear" );

   SDL_Rect windowedRect;

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

   int32_t flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE;
   flags |= SDL_WINDOW_FULLSCREEN;

   SDL_Rect resolution;
   resolution = windowedRect;

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



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


   // start the renderer
   m_RenderThread = new std::thread( RenderThread );


   // main loopy thing
   while ( 1 )
   {
      if ( quitGame )
      {
         break;
      }

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

      Sleep( 10 );
   }


   // kill the renderer thread
   stopRenderer = true;
   m_RenderThread->join();
   delete m_RenderThread;
   m_RenderThread = nullptr;


   // desroy the window
   SDL_DestroyWindow( m_Window );
   m_Window = NULL;


   SDL_Quit();
   return 0;
}

lemmn


Joined: 18 Jun 2016
Posts: 5
Ok, I would like to fix a few more things but I can't edit and I don't want to post the same thing over and over.
lemmn


Joined: 18 Jun 2016
Posts: 5
Ok, I would like to fix a few more things but I can't edit and I don't want to post the same thing over and over.
lemmn


Joined: 18 Jun 2016
Posts: 5
I notice I also have problems with resizing the window. The program crashes. Am I trying to do something that isn't possible???

This game's main loop where I process input needs to spin extremely fast! Because i need sub-millisecond accuracy on input handling. I need to get those events as fast as possible.

So, my rendering cannot happen in the loop where I handle input.

I need to be able to either render or handle input in a separate thread. Is either thing possible?