oldmanmike oldmanmike - 1 month ago 13
C++ Question

SDL_PollEvent seems to prevent window surface from updating

I'm currently walking through the Lazy Foo tutorials for SDL2 (I'm doing this on a Linux machine) and I'm encountering some kind of bug where the inclusion of

SDL_PollEvent
in my main loop seems to prevent
SDL_UpdateWindowSurface
from actually updating. If I leave the
SDL_PollEvent
loop out, the loaded bmp displays properly. However, if I include the
SDL_PollEvent
loop or even a call to
SDL_PollEvent
, then the window never gets updated with an image. Everything else seems to work fine,
SDL_PollEvent
is queuing events properly and the loop handles the events properly, but for some reason there's a visual discrepancy between the inclusion of
SDL_PollEvent
vs. leaving it out.

Using the code provided by Lesson 03: Event driven programming:

This loop fails to update the window:

while( !quit )
{
//Handle events on queue
while( SDL_PollEvent( &e ) != 0 )
{
//User requests quit
if( e.type == SDL_QUIT )
{
quit = true;
}
}

//Apply the image
SDL_BlitSurface( gXOut, NULL, gScreenSurface, NULL );

//Update the surface
SDL_UpdateWindowSurface( gWindow );
}


This loop successfully updates the window with the loaded image:

while( !quit )
{

//Apply the image
SDL_BlitSurface( gXOut, NULL, gScreenSurface, NULL );

//Update the surface
SDL_UpdateWindowSurface( gWindow );
}


But it stops working with the inclusion of a single call to
SDL_PollEvent
:

while( !quit )
{
SDL_PollEvent(&e);

//Apply the image
SDL_BlitSurface( gXOut, NULL, gScreenSurface, NULL );

//Update the surface
SDL_UpdateWindowSurface( gWindow );
}

Answer

SDL_GetWindowSurface documentation says This surface will be invalidated if the window is resized. Upon initial window creation several events are generated, like SDL_WINDOWEVENT_SHOWN and SDL_WINDOWEVENT_EXPOSED. While window isn't marked as user-resizable, I suppose window manager still have an ability to perform resize; you may want to check which events are placed in your event queue (as I cannot reproduce your problem - may be e.g. window manager specific).

To put it in other worlds, window surface isn't guaranteed to persist after some events, so theoretically flushing event queue can invalidate surface. You need to get window surface after flushing event queue just before drawing, on each frame:

while( !quit )
{
  // event loop here

  // get surface to draw on
  gScreenSurface = SDL_GetWindowSurface(gWindow);

  //Apply the image
  SDL_BlitSurface( gXOut, NULL, gScreenSurface, NULL );

  //Update the surface
  SDL_UpdateWindowSurface( gWindow );
}
Comments