I'm experiencing some weird graphical corruption with my SDL2 + OpenGL GUI application. Now I apologize if I'm not using the appropriate term to describe the situation. It seems that the front buffer is being invalidated and other applications are being drawn in the buffer?
Important note: this corruption only occurs in Windows XP or when using the Windows Basic theme in Windows 7.
The corruption can be reproduced in a few ways:
- by moving the window around. It seems that the front buffer gets corrupted with the image of other applications in front or behind it.
- if there's an application behind, it'll occasionally flash into the front buffer.
- I can load up a google webpage in Chrome above the opengl application, close the chrome process, and then move the opengl application around and I'll see the google homepage covering the whole inside of the window.
- by moving another application over the opengl window.
It seems that I also see the corruption when I'm moving other windows around, even if they don't overlap the opengl window, so long as I've already tried one of the ones posted just above.
inline int UI::RenderingThread()
{
UI::Window::Instance().RenderingThreadEnter();
while( UI::Window::Instance().RenderingThreadActive() )
{
unsigned int ticks = SDL_GetTicks();
UI::Window::Instance().RenderingThreadUpdate();
UI::Window::Instance().RenderingThreadRender();
ticks = SDL_GetTicks() - ticks;
if( ticks < 33 )
{
SDL_Delay( 33 - ticks );
}
}
UI::Window::Instance().RenderingThreadExit();
return 0;
}
As you probably guessed, I'm using multithreading and I have my rendering in a separate thread. Within the RenderingThreadRender()
function, I only redraw if there's a change in content, or I've requested a redraw.
case SDL_WINDOWEVENT:
switch( sdl_event.window.event )
{
default:
UI::Window::Instance().Redraw();
break;
}
This is done to allow all SDL_WINDOWEVENT
events to redraw in hopes that one of them would fix the problem. Unfortunately that has not solved the issue.
I'm hesitant to simply constantly redraw my application at 30 or 60 fps since I've noticed that by doing so, other application would be sluggish when moving them around.
Initialization:
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
this->window = SDL_CreateWindow( this->caption.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
UI::WindowSize::Instance().GetWindowWidth(), UI::WindowSize::Instance().GetWindowHeight(),
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE );
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glViewport(0, 0, UI::WindowSize::Instance().GetWindowWidth(), UI::WindowSize::Instance().GetWindowHeight());
// Set the OpenGL view
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( 0, UI::WindowSize::Instance().GetWindowWidth(), UI::WindowSize::Instance().GetWindowHeight(), 0, -1, 1 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
glDisable( GL_DITHER );
Rendering:
if( this->redraw )
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
// a few DrawArrays
SDL_GL_SwapWindow( this->window );
}
Does anyone have any idea what could be causing this issue, and how to fix it?
EDIT: Some more research has pointed me to the following two questions:
C++ OpenGL window only tracks background
However, this doesn't solve my problem since I'm already using Double Buffering.
CS_OWNDC
first and foremost.CS_HREDRAW
andCS_VREDRAW
as well. Unfortunately, SDL hides all of this stuff from you, and I think it actually defaults toCS_OWNDC
. I have to suspect that Windows is sending your applicationWM_PAINT
events that for whatever reason SDL is not forwarding to you, and this is why you get the corruption every so often. – Andon M. Coleman