Reputation: 77
I have a little problem.
I have a window with OpenGL child window, All the Opengl window does so far is renders a texture on the bottom right of the window.
if i resize the window really fast from the left to the right the texture sometimes moves left, its like its not repainting fast enough even know im drawing direct to the opengl context.
The only way i have removed the problem is to InvalidateRect of the opengl window when main window resized, But im not sure why that fixes the issue because im drawing to the opengl context so i shouldnt need to make it paint its self after i have painted to the context.
if bHandled
is false the defWndProc is called else it returns the function
Main window WM_SIZE
int ControllerMainWnd::OnSize(WPARAM wParam, LPARAM lParam, bool & bHandled)
{
bHandled = true;
int width = LOWORD(lParam);
int height = HIWORD(lParam);
//Set OpenGL Window Size
::SetWindowPos(glHandle, 0, 0, 0, width, height, SWP_NOZORDER);
//Invalidate OpenGL Window
::InvalidateRect(glHandle, 0, FALSE); // if i comment this out my texture sometime moves
return 0;
}
OpenGL window
int ControllerGL::OnPaint(WPARAM wParam, LPARAM lParam, bool & bHandled)
{
//bHandled = true;
//LRESULT lRes = defWinProc(WM_PAINT, wParam, lParam);
Paint();
//return lRes;
return 0;
}
int ControllerGL::OnSize(WPARAM wParam, LPARAM lParam, bool & bHandled)
{
bHandled = true;
int width = LOWORD(lParam);
int height = HIWORD(lParam);
modelGL->setWindowSize(width, height);
Paint();
return 0;
}
int ControllerGL::OnEraseBkgnd(WPARAM wParam, LPARAM lParam, bool & bHandled)
{
bHandled = true;
return 1L;
}
auto ControllerGL::Paint() -> void
{
openGLcontext->activateContext();
modelGL->draw();
openGLcontext->swapBuffers();
}
Upvotes: 2
Views: 1214
Reputation: 36026
Your problem would probably be associated with the fact that you are causing the window to repaint 2 times every time you move the mouse during a resize.
First, Windows automatically invalidates the windows area when you resize it (you can control this with with the class styles CS_HREDRAW and CS_VREDRAW that should always be set for OpenGL windows as a resize typically needs a full window redraw).
Then you (redundantly) manually invalidate the window rect. Then you force it to paint - with a future paint now queued.
The OnPaint handler for a OpenGL window should really look like:
int ControllerGL::OnPaint(WPARAM wParam, LPARAM lParam, bool & bHandled)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd,&ps);
wglMakeCurrent(hdc,hglrc);
scene->Display();
SwapBuffers(hdc);
wglMakeCurrent(hdc,NULL);
EndPaint(hwnd,&ps);
bHandled = true;
return 0;
}
I leave it as an exercise to properly encapsulate the hwnd and hglrc, writing it in this way shows you explicitly that SwapBuffers works on a DC, not on the implicit OpenGL context, and that wglMakeCurrent should be scoped with a dynamically obtained window DC.
Most OpenGL samples are very VERY lazy and use a class DC and simply leave the openGL content "active" all the time but that's going to fail as soon as two windows on the thread are trying to do OpenGL. Far better to omit the CS_OWNDC (if you have it) and get (and release) the DC whenever you actually need it.
i.e. If you wanted to handle your WM_SIZE more traditionally (similar to the glut Reshape callback) you would do this:
int ControllerGL::OnSize(WPARAM wParam, LPARAM lParam, bool & bHandled)
{
bHandled = true;
int width = LOWORD(lParam);
int height = HIWORD(lParam);
HDC hdc = GetDC(hwnd);
wglMakeCurrent(hdc,hglrc);
scene->Reshape(width,height);
wglMakeCurrent(hdc,NULL);
ReleaseDC(hwnd,hdc);
return 0;
}
Every other call from ControllerGL
into what I call scene
and you call modelGL
would be similarly wrapped.
Upvotes: 1