PDA

View Full Version : DWM...problems and investigations



s252019
06-25-2010, 12:43 AM
Hello there!

I'm writing a sort of CAD application, and I have a problem with lines "following" the mouse when the DWM is active (other CAD applications seems to have it too).
The problem can be simplified like this:
I render a line with the end point following the "current mouse position". Without the DWM, if I enable vsync it renders at 60FPS, if I disable it it renders at 400FPS. The line extreme always UNDER the mouse,in both cases.

When I enable the composition in Vista/Win7, the line is delayed in respect to the mouse, there's a noticeable lag between the mouse move and the line following it. Since WDM is on, the vsync is always active, and the "effective" present-on-video rate is at most 60FPS (on my screen).
In reality,using WDMGetTimingInfo I find that the effective refresh rate is 35FPS.

This causes the line to be always behind the actual mouse position, since there's a delay from when I call SwapBuffer and when the DWM updates the video.
I already tryed to use Single Buffering, to drop the framerate, to adjust the DWM settings but without luck. The only solution is to disable the DWM. From what I understand this problem would be present using DirectX too, but I'm not sure at 100%

This effect is annoying in particular when the user draws rubber band lines.

I've tested a bunch of CADs and a lot have this problem too. But, for example, Google Sketchup doesn't have this is issue, since the mouse is always responsive. Rhino on the other hand has it (tryed the v4 demo). Both use OpenGL.
So I guess this can be resolved anyhow.

There should be a way to force the DWM to repaint... at least the OpenGL window.

Any advice to give?

Thank you,
Qb

Pierre Boudier
06-25-2010, 03:14 AM
your issue is not because of the opengl rendering part, but because DWM is a separate process which composites the desktop and presents it to the display once available. afaik, this separate process is scheduled against all other processes generically.

even if you were to call glFinish() inside opengl, you would have no guarantee that the desktop content is refreshed. and DWM is compositing the desktop for either single/double buffered application (the front buffer is not shared with the desktop unlike XP)

one option (workaround?) for you is to deactive DWM; there is an OS API for this.

sammie381
06-25-2010, 04:43 PM
your issue is not because of the opengl rendering part, but because DWM is a separate process which composites the desktop and presents it to the display once available. afaik, this separate process is scheduled against all other processes generically.

even if you were to call glFinish() inside opengl, you would have no guarantee that the desktop content is refreshed. and DWM is compositing the desktop for either single/double buffered application (the front buffer is not shared with the desktop unlike XP)

one option (workaround?) for you is to deactive DWM; there is an OS API for this.

Yes, you can programmically turn off DWM, but this is very ugly.
The entire screen goes black, and Vista/Win7 pops up a warning message saying DWM was just turned off.
It's like we're being punished for trying to make our program run more smoothly.

If one could suppress this ugly warning, then it would much nicer.

Alfonse Reinheart
06-25-2010, 07:48 PM
Yes, you can programmically turn off DWM, but this is very ugly.
The entire screen goes black, and Vista/Win7 pops up a warning message saying DWM was just turned off.
It's like we're being punished for trying to make our program run more smoothly.

If one could suppress this ugly warning, then it would much nicer.

But it's not your computer; it's your users' computer. I know if I was running a program that decided of its own accord to turn off OS functions, I'd like the OS to notify me of that fact.

If the DWM is getting in your way, perhaps it would be better to let the user know and tell them that they will get degraded performance unless they deactivate the DWM.

sammie381
06-25-2010, 10:34 PM
Yes, you can programmically turn off DWM, but this is very ugly.
The entire screen goes black, and Vista/Win7 pops up a warning message saying DWM was just turned off.
It's like we're being punished for trying to make our program run more smoothly.

If one could suppress this ugly warning, then it would much nicer.

But it's not your computer; it's your users' computer. I know if I was running a program that decided of its own accord to turn off OS functions, I'd like the OS to notify me of that fact.

If the DWM is getting in your way, perhaps it would be better to let the user know and tell them that they will get degraded performance unless they deactivate the DWM.

What Microsoft should have done, is display the DWM warning as a popup notification on the taskbar. This is a much nicer way
of displaying information. Otherwise, your program will just scare away new users when the screen goes black.

Alfonse Reinheart
06-25-2010, 10:41 PM
What Microsoft should have done, is display the DWM warning as a popup notification on the taskbar. This is a much nicer way of displaying information.

But it's not "displaying information." It's telling the user that a program (which may not have been something he asked to run. ie: malware) has decided to modify his system's settings. This is not a minor event that the user should be able to easily ignore. Turning off the DWM has consequences, effects that a user might not want to have happen. He might be using that DWM, after all.

That's why I say you should explicitly ask the user. It's just common courtesy; you wouldn't knock down a wall on a friend's house without asking. Let the user decide if he wants improved performance for your application at the expense of whatever the DWM was doing for him before your application came along.

And if your app crashes, are you going to properly ensure that the DWM is restored if you had to turn it off?

sammie381
06-26-2010, 12:22 AM
What Microsoft should have done, is display the DWM warning as a popup notification on the taskbar. This is a much nicer way of displaying information.

But it's not "displaying information." It's telling the user that a program (which may not have been something he asked to run. ie: malware) has decided to modify his system's settings. This is not a minor event that the user should be able to easily ignore. Turning off the DWM has consequences, effects that a user might not want to have happen. He might be using that DWM, after all.

That's why I say you should explicitly ask the user. It's just common courtesy; you wouldn't knock down a wall on a friend's house without asking. Let the user decide if he wants improved performance for your application at the expense of whatever the DWM was doing for him before your application came along.

And if your app crashes, are you going to properly ensure that the DWM is restored if you had to turn it off?

There are tons of system settings you can change without having Windows complain about it.
DWM is just an ugly exception.

Alfonse Reinheart
06-26-2010, 04:12 AM
There are tons of system settings you can change without having Windows complain about it.

Then clearly Microsoft should add more warnings, not take away this one.


DWM is just an ugly exception.

Considering that the DWM affects every window and the fundamental nature of the entire UI from the user perspective, that's entirely understandable. By turning off the DWM without asking, you are doing something unpleasant to the user's machine. Windows has every right to interrupt this request and notify the user in no uncertain terms.

Also, it keeps developers from treating the DWM as optional. It's something you only try to turn off if you have absolutely no alternative.

mhagain
06-27-2010, 09:17 AM
There are tons of system settings you can change without having Windows complain about it.
DWM is just an ugly exception.

Windows isn't complaining about it. Windows is saying to the user "Heads up mate, an application is trying to change a setting that is going to affect other applications you might also be running behind your back". This is a Good Thing - your application is not the only one on the user's system, and you should not act as if it were.

Furthermore, switching off the DWM smacks of treating the symptoms, not the cause. It's been established that the DWM and OpenGL can interoperate cleanly (hell, it even works with Quake!) so let's find out why it's not working here, eh?

So back to the OP; have you tried the guidelines given here (http://www.opengl.org/pipeline/article/vol003_7/) for ensuring correct interoperation with the DWM?


On the other hand, if a developer wants to have Windows Aero enabled with a windowed OpenGL application, use the following rules to verify that you are not inadvertently trying to mix GDI over OpenGL: Create an OpenGL context using a pixelformat with compositing support (PFD_SUPPORT_COMPOSITION set). Handle the application window's WM_ERASEBKGND by returning non-zero in the message handler (this will avoid GDI clearing the OpenGL windows' background). Verify that the OpenGL window has the proper clipping styles WS_CLIPCHILDREN or WS_CLIPSIBLINGS, so GDI rendering of sibling windows in the layout hierarchy is not painted over and vice versa. Repaint the application's windows as they are being resized rather than when the final resize happens. This will avoid interacting with GDI's xor drawing of the window border. For example, if the application has splitter bars in a four-viewport application, resize the viewports as the splitter bar is being dragged, otherwise GDI xor rendering over the OpenGL viewport will leave trails. Do not use GDI for xor drawing of "rubberbands" or selection highlighting over the OpenGL rendering. Use OpenGL logical operations instead. Do not get the desktop's DC and try to paint over it with GDI, as it will corrupt the 3D-accelerated regions. Under the DWM's new architecture it is especially important that an application developer verify that the application pairs GetDC/ReleaseDC appropriately. The same goes for LockWindowUpdate and LockWindowUpdate(NULL).

sammie381
06-27-2010, 02:10 PM
Furthermore, switching off the DWM smacks of treating the symptoms, not the cause. It's been established that the DWM and OpenGL can interoperate cleanly (hell, it even works with Quake!) so let's find out why it's not working here, eh?


Games are poor examples of what works with DWM. They are either full-screen or completely render their own GUIs.

Try to do something with MFC, OpenGL, and real-time rendering, and you will start getting refresh problems and flickering garbage.
For example, the CSplitterWnd class is an ugly nightmare.

mhagain
06-27-2010, 02:18 PM
Furthermore, switching off the DWM smacks of treating the symptoms, not the cause. It's been established that the DWM and OpenGL can interoperate cleanly (hell, it even works with Quake!) so let's find out why it's not working here, eh?


Games are poor examples of what works with DWM. They are either full-screen or completely render their own GUIs.

Try to do something with MFC, OpenGL, and real-time rendering, and you will start getting refresh problems and flickering garbage.
For example, the CSplitterWnd class is an ugly nightmare. Fair enough but the rest of my point still holds. Unless one is absolutely hell-bent on switching off the DWM even in the face of a documented and clear set of instructions for interoperating, why not just follow those instructions?

sammie381
06-27-2010, 06:52 PM
Fair enough but the rest of my point still holds. Unless one is absolutely hell-bent on switching off the DWM even in the face of a documented and clear set of instructions for interoperating, why not just follow those instructions?

Easier said than done!

Microsoft needs to re-write their splitter class to work with 3D viewports, so they are flicker-free on Vista/Win7.
I've done all I can, and I still get garbage.

s252019
06-28-2010, 12:34 AM
Thank you for the answers.
Of course disabling the DWM would have a negative impact, since is a feature of Windows and I find it really annoying for the user.

The key point here is the noticeable lag between the SwapBuffers and the presentation on the screen. This would not be a problem even in the most common cases, since 40 FPS is enought for CAD , exept when the user is doing interactive things (like drawing).
In this case the lines are always "late" in respect to the screen position.

I'm looking for a solution to this problem since I see that some softwares behave correctly in the same situation.
I have already (unsuccessfully) tryed:

- Using single buffering
- Using a framerate below the composition refresh rate
- Setting various DWM parameters using specific API, etc...

I'm following the DWM guidelines, given that my test application is a simple app that does updates a line following the current mouse position.

also, I would like to try to use DXGI API somehow to decrease this lag, but I didn't find a way to do this in cooperation with OpenGL.

sammie381
06-28-2010, 02:20 PM
Thank you for the answers.
Of course disabling the DWM would have a negative impact, since is a feature of Windows and I find it really annoying for the user.

The key point here is the noticeable lag between the SwapBuffers and the presentation on the screen. This would not be a problem even in the most common cases, since 40 FPS is enought for CAD , exept when the user is doing interactive things (like drawing).
In this case the lines are always "late" in respect to the screen position.

I'm looking for a solution to this problem since I see that some softwares behave correctly in the same situation.
I have already (unsuccessfully) tryed:

- Using single buffering
- Using a framerate below the composition refresh rate
- Setting various DWM parameters using specific API, etc...

I'm following the DWM guidelines, given that my test application is a simple app that does updates a line following the current mouse position.

also, I would like to try to use DXGI API somehow to decrease this lag, but I didn't find a way to do this in cooperation with OpenGL.

Both OpenGL and DirectX go through the DWM, so I don't see why that would matter.

Diagram here:
http://www.opengl.org/pipeline/article/vol003_9/

And DXGI is just some abstraction of D3D. They are essential the same on the graph.

But, if you decide to use it, your program will only run on Vista/Win7. DXGI is not supported on Windows XP.
Unlike OpenGL, which does.

s252019
06-29-2010, 12:12 AM
In fact, I would like to use DXGI just to try to do a bit of syncronization between our application and the screen presentation. Of course I would use this tecnology only under VISTA/WIN7, since XP doesn't have this problem.

loopless
07-02-2010, 02:20 PM
I am having identical problems ( and agree with the OP) on Vista/W7 when "aero" is active in our MFC/OGL based CAE style application.

- MFC CSplitterWnd resizing leaves 'window garbage' behind
- How to draw an interactive zoom box (using XOR operations) on the OpenGL window - we were using GDI, of course this is a no-no now.

We have to advise the user to revert to Windows 7 basic theme. Of course they never read the release notes, so support gets the call....

No-one seems to have a 100% solution to this.

sammie381
07-04-2010, 06:35 PM
I am having identical problems ( and agree with the OP) on Vista/W7 when "aero" is active in our MFC/OGL based CAE style application.

- MFC CSplitterWnd resizing leaves 'window garbage' behind
- How to draw an interactive zoom box (using XOR operations) on the OpenGL window - we were using GDI, of course this is a no-no now.

We have to advise the user to revert to Windows 7 basic theme. Of course they never read the release notes, so support gets the call....

No-one seems to have a 100% solution to this.

They expect you to resize the viewports in real-time now, so drawing the XOR crossbar is no longer necessary.

But of course, nobody is going to tell you how to do it. I've overloaded some CSplitterWnd class member functions,
but either redrawing is slow, or something is not getting updated correctly, because I still get trailing garbage
around the crossbars.


You might have like 4 OpenGL viewports surrounded by GDI splitterbars. To resize the GL viewports and redraw
the GDI splitterbars at the same time, means that the drawing of both have to be perfectly synchronized.
I tried calling glFlush() and GdiFlush() at the same time to synchronize my drawing between them, but as far
as I can tell, it's not working.