PDA

View Full Version : HELP! dialog outline remains after screen draw



RJH
08-12-2002, 06:11 PM
HELP! I've written a Win32 SDI app using OpenGL and the MFC. Whenever I have to draw the screeen, I also create a modeless dialog with a progress control to show how the rendering is progressing. Some of the beta testers of this app are reporting that after the screen is refreshed they can see the new screen image but are also stuck with a blank or grey rectangle where they progress dialog used to be and they can't get rid of it. I cannot reproduce this situation and not everyone is experiencing this problem. Any ideas on what might be happening to these few individuals? Code snippet is:


void CView::OnDraw(CDC* pDC)
{
...

// Create the modeless Progress dialog
pProgDlg = new CProgDlg();
ASSERT (pProgDlg);
pProgDlg->Create(IDD_PROGRESS_DIALOG, this);
pProgDlg->ShowWindow(SW_SHOWNORMAL | WS_CHILD);

// render client area using OpenGL
DrawScreen(pProgDlg);
// get rid of progress dialog
pProgDlg->DestroyWindow();
delete pProgDlg;
pProgDlg = NULL;

// exchange display buffers
SwapBuffers(pDC->m_hDC);

...
}


void CProgDlg::OnDestroy()
{
CDialog::OnDestroy();
}

Korval
08-12-2002, 06:37 PM
It seems pretty simple: it's a race condition.

When you call "DestroyWindow", the window is, apparently, not instantly destroyed. Maybe it takes some time for it (and its child windows) to actually go away. If any window is still there when you call SwapBuffers, then the parts of the display still hidden will not display correctly.

If this is the case, you need to set your code up so that it blocks (sitting in a while loop) until pProgDlg finishes processing it's WM_NCDESTROY message. Then, you know the windows are gone.

BTW, if this is the case (and I'm not sure it is, but it seems to fit the facts), running "delete pProgDlg" right after destroying the window could cause a problem. Instead, put this line after your blocking while loop.

Relic
08-13-2002, 01:24 AM
This sounds as if you assume the pixels under the dialog get actually rendered in the back buffer. That's a wrong assumption!
Pixels which are not exposed on the OpenGL rendering window do not belong to the OpenGL context, this includes all(!) bits per pixel including front, back, depth, stencil, etc.
Results are undefined, aka. implementation dependent. That's why different testers have different results.
You need to respond to all WM_PAINT messages you get. This includes your own slider window, which is pretty useless then, because you'll programmed an endless loop.
Create your slider somewhere else, in the status bar for example, or print a percentage in the title bar. And don't update it too often.

kevinhoque
08-13-2002, 02:25 AM
Why not bring the main window to the front when the dialog is destroyed? This should move the remnants of the dialog behind the main window and also result in a paint message being sent to the main window also?

Kevin

Relic
08-13-2002, 04:55 AM
Because the drawing in the main window underneath the dialog doesn't happen in the first place. And if you need to redraw with the same OnDraw() handling, you get another slider window, and so on ...
This OnDraw() function is architecturally broken. Don't create windows on top of your drawing window in the WM_PAINT handler!

bpeers
08-13-2002, 07:01 AM
If it only happens on NVidia, it could be a driver bug -- try getting the latest detonator 30.82

http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/007082.html .

edit UBB 0wnz me


[This message has been edited by bpeers (edited 08-13-2002).]

kevinhoque
08-14-2002, 02:48 AM
Relic, perhaps I misunderstood the original question. Is RJH writing a renderer to generate non-realtime graphical data? If this is so then don't you think that it would be better for him if he did the actual rendering himself using a custom software renderer and then only use opengl for previews etc. Seems a little dangerous to assume that the opengl viewport/s will not be obscured during rendering in a normal windows working environment.

If it is some realtime renderer/application (which I now suspect is not the case) then using something akin to an MFC version of SetWindowPos with the appropriate parameters to bring the main window forward (along with any child windows) should result in the OnPaint msg handler being called, hopefully without any other windows obscuring the views...Still not guaranteed though.

Nice speaking to you...
Kevin

Relic
08-14-2002, 03:04 AM
I hold my position that the above OnDraw() handler is generally broken for any kind of drawing.
And assuming pixel contents of unexposed window areas (overlapped or moved off the desktop) is not correct.
Some implementations will have less problems with this, like MS GDI generic which has it's complete backbuffer unclipped in host memory, but for front buffered rendering this is obviously not working. That is what the testers see, generally undefined behaviour among implementations. This has nothing to do with driver bugs.

The purpose of a WM_PAINT handler is to paint the client view of a window. Overlapping windows are going to be clipped by the windowing system. How that is handled in the OpenGL case is implementation dependent. Removing the overlapping window will generate a new WM_PAINT message on the client again, so it's utter nonsense to generate a window overlapping the client in the same routine that actually draws onto that client area. Period.
(Sorry getting tired, of this simple problem. http://www.opengl.org/discussion_boards/ubb/wink.gif)

kevinhoque
08-14-2002, 03:28 AM
Ahh. Now I see what you're banging on about. I thought that perhaps when the dialog was killed for some strange reason the opengl client window wasn't receiving a paint msg and so in this context I gave a possible solution. Still don't think that relying on opengl to render out non-realtime scenes (other than for preview purposes) is particularly wise - if that is indeed what is happening here. Just my $0.02 http://www.opengl.org/discussion_boards/ubb/smile.gif

tcobbs
08-14-2002, 09:17 AM
I noticed similar behavior using an nVidia card, but the behavior I saw indicated that all of the nVidia OpenGL rendering seemed to work correctly in the back buffer EXCEPT for glClear(). In other words, the rendering happened fine, but the part under the progress dialog didn't get cleared.

I was able to work around this at the time by drawing a window-sized quad with max Z value and depth test disabled, but I am currently in the process of moving my progress updates into a status bar in an attempt to make things work on all hardware.

RJH
08-15-2002, 12:52 AM
Originally posted by Relic:
This sounds as if you assume the pixels under the dialog get actually rendered in the back buffer. That's a wrong assumption!
Pixels which are not exposed on the OpenGL rendering window do not belong to the OpenGL context, this includes all(!) bits per pixel including front, back, depth, stencil, etc.
Results are undefined, aka. implementation dependent. That's why different testers have different results.


Thanks to all who responded - I appreciate it. I think Relic identified the problem.