§ ¶DirectDraw rendering glitches with multiple displays
It's been reported to me that an odd thing happens on systems with multiple monitors where VirtualDub will repeatedly lock up the system with display flashes whenever the display panes overlap the second monitor. I saw this in person once, but unfortunately wasn't in a position to debug it, and only recently have been able to recreate it on my debug station. The circumstances where this occurs are:
- DirectDraw display mode is enabled (default).
- Direct3D/OpenGL display mode is not enabled (default).
- Some part of a display pane overlaps a non-primary monitor.
I think another condition is "you have an NVIDIA video card," but a sample size of two with all NVIDIA cards isn't conclusive. Might be XP-only, too.
When this happens, the display will flash and the entire system locks up for about half a second every time VirtualDub tries to repaint the panes. Joy. The workaround is to change the display options in Options > Preferences > Display, and either disable DirectX support (slow) or enable Direct3D mode (preferred).
I traced through this a bit and the entire effect occurs in IDirectDrawSurface3::Blt(). There doesn't appear to be anything special about this call except the destination rectangle. I managed to reproduce this effect on at least two other DirectDraw-based applications, unfortunately, so that means I'm likely in workaround territory rather than fix territory. I also wasn't able to break into the debugger during the call to find out what exactly was locking everything up since the debugger was also frozen, which means resorting to CDB or a remote kernel-mode debugger. If I can't figure any other solution, I'll probably just manually clip the destination and source rectangles to the primary monitor. VirtualDub doesn't currently instantiate a DirectDraw context per adapter and so it can't render on the secondary monitor that way anyway, and clip precision isn't an issue because the DirectDraw runtime already only clips to integer precision -- the lack of subpixel precision is why weird artifacts appear when you drag another window on top of a DirectDraw-based application that's doing a stretchblt.
I faced something similar (might be related) when I was writing a custom Direct3D Presenter for VMR9. Basically, any hardware accel would only work on the primary screen. You had to specify the monitor handle in several places to gain acceleration on other screens.
Blight - 21 09 09 - 21:00
I actually have it on my work-computer. I thought it was because I run Dualview, but with each screen at a different resolution. But it doesn't lock up here, it simply draws junk over the entire virtualdub window.
Klaus Post (link) - 22 09 09 - 01:07
No problems with that on my system:
WinVista Business x64 SP2
screen 1 1280x1024, screen 2: 1920x1200
Geforce GTX 280 / 190.62
Chris - 22 09 09 - 03:03
@Chris: Windows XP here, so Avery might be right in his assumption, that it is XP only. You can see an example here:
You can just see the menu items at the top, where I rolled over with the mouse. Reproduction is exactly as Avery described, except that I have to move the window for the entire window to become junk - before that only the overlay itself is junk.
To me it looks like a driver error, since the junk inside the window is actually content from another part of the screen with wrong pitch, and if I move the window around the junk offset changes.
Klaus Post (link) - 22 09 09 - 21:21
Huh, indeed an "interesting" screenshot :-)
Are you using up-to-date drivers ?
Chris - 23 09 09 - 06:49
Ooh, I'll bet I know what's going on.
I heard a while ago that on XP, GDI does something quite evil in certain cases: it attempts to emulate correct dual monitor support for rendering operations by blitting. Problem is, in usual GDI fashion, this blit is butt slow because it involves reading from the video card down to system memory and then uploading it again, even if it ends up being the same video card. To circumvent this, video driver writers have had to put in certain hacks into their drivers to detect the blit and accelerate it on the card itself. It's possible that for some reason this isn't happening anymore with newer drivers -- it might have been causing bugs or Microsoft may have broken it in an update.
In any case, I can also confirm that this is also a problem with Direct3D9. That doesn't surprise me, because under the hood it uses a variant of ye olde DirectDraw blit in order to do Present(). However, D3DPRESENTFLAG_DEVICECLIP does fix the problem and doesn't cause the subpixel inaccuracy that manual clipping does.
Phaeron - 23 09 09 - 18:52