Skip to main content
GameDev.net gamedev.net
🔒 Locked

[C++] DirectDraw Overlay Library

Started by Muhammad Haggag Apr 24, 2007 at 1:46 PM 14 replies 36.9k views
Original Post
Muhammad Haggag
Muhammad Haggag
I have created a C++ overlay library based on the C++ Overlay Sample published almost a year and a half ago. It improves a number of things over the sample: 1. It works on nVidia cards, using either the YUY2 or UVYV surface formats. 2. It is packaged as a C++ library. A C++/CLI wrapper will be written as soon as I fix any outstanding issues with the native library. 3. A better sample is included, which shows how one can blit a window to the overlay. The project page can be found on Codeplex, here. Currently, the only available release is 0.5b, which includes 3 files: 1. DirectDrawOverlay-lib-0.5b.zip, the release and debug builds of the library. 2. DirectDrawOverlay-bin-0.5b.zip, the sample binary files. 3. DirectDrawOverlay-src-0.5b.zip, the source code (VS8 solution). Build instructions can be found at the project homepage. The sample Details on what the sample does can be found here. The YUV issue There's a known issue with YUV formats--i.e, on nVidia cards--where the colors for some controls are messed up. Most notably, black-text-on-white is shown in the overlay as white-text-on-black. It's on my TODO list, and it's probably some silly conversion error, so ignore this for now. I need your help I need people with pre-Vista systems to test the sample on any fullscreen games they have, both Direct3D and OpenGL ones. So far, the one XP tester I had has never reported failure. With Vista systems, the situation is rather strange. The 2 Vista testers I had reported that: 1. Fullscreen DirectX SDK samples work fine with the overlay. 2. Fullscreen Direct3D applications other than the samples cause the overlay to be lost. 3. Fullscreen OpenGL applications cause the overlay to be lost. It's not entirely clear what's going on with #2, perhaps it has to do with multisampling or some setting used by the games by default. No idea what's going on with #3, though. It's either related to the new Vista driver architecture, or a driver issue. Further testing should provide some clues. Please include your graphics card type and driver version with any error reports.

Muhammad Haggag
Muhammad Haggag
If you get an "Application configuration is incorrect" error on launching the sample, that means you don't have the updated VC++8 SP1 runtime DLLs. I have uploaded the runtime installer vcredist_x86.exe to the release.

jollyjeffers
jollyjeffers
I don't have VC8-SP1, Boost or wxWidgets installed so I can't build anything [headshake]. I needed to install the VC8 SP1 runtimes before I could get the standalone binaries running...

My results:

  • Windows XP Professional 32bit
  • Nvidia GeForce 6800 512mb RAM. I updated to latest drivers a week or so back, but not sure which version.

    Running on the desktop - works as expected, but display is a bit fuzzy (almost like slightly off bilinear filtering) as well as muddy colours - their mostly correct, but the background of the textbox is light grey instead of white for example. If I drag the window off one edge of the display then I get a corresponding black area in the overlaid copy...

    Windowed and fullscreen mode D3D9 sample apps don't seem to make any difference - it keeps on trucking [smile]

    Fullscreen video via WMP (I understand some codecs use overlays?) is absolutely fine as well.

    Running a couple of non-SDK tech demo's wasn't quite so successful:

    The ancient 'The Project' demo from ATI/CryTek managed to hide the overlay.

    The 'Illuminatu' demo (another old one, forget where from) worked okay - overlay appeared as expected.

    Couldn't find any other samples worth running - most of mine are based on the DXUT/SDK framework and my Anti-Virus software removes any OpenGL code from my system [wink]

    Jack
  • <hr align="left" width="25%" />
    Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ |
    Muhammad Haggag
    Muhammad Haggag
    Quote:
    Original post by jollyjeffers
    I don't have VC8-SP1, Boost or wxWidgets installed so I can't build anything [headshake].

    Indeed, this is a bit of an issue. There's no way to work around this with wxWidgets, since it's a huge dependency, but I'll look into incorporating the headers I use from boost into the source tree.

    Quote:
    Running on the desktop - works as expected, but display is a bit fuzzy (almost like slightly off bilinear filtering) as well as muddy colours - their mostly correct, but the background of the textbox is light grey instead of white for example.

    This is due to the RGB<->YUV conversion. I'm not doing it 100% right, it seems. I have to do some analysis on my code to see why the colors are inverted at places.

    Quote:
    Fullscreen video via WMP (I understand some codecs use overlays?) is absolutely fine as well.

    I don't think modern codecs use DirectDraw overlays anymore, but I could be wrong. Either way, glad it's working.

    Quote:
    The ancient 'The Project' demo from ATI/CryTek managed to hide the overlay.

    Is that a D3D9 demo? Incidentally, does it take a relatively long time to "activate" fullscreen operation? I have no idea what's going on, but the fullscreen applications that don't work seem to take a long time to enter fullscreen, while the samples are almost instantaneous.

    Quote:
    Couldn't find any other samples worth running - most of mine are based on the DXUT/SDK framework and my Anti-Virus software removes any OpenGL code from my system [wink]

    Umm..don't you have any games MR UBER GEEK? :P

    Thanks a lot for the tests, much appreciated [smile].

    Muhammad Haggag
    Muhammad Haggag
    Does the demo, "The Project", have multi-sampling enabled? I just tested with one of the SDK samples. The overlay disappears if I tell the sample to go fullscreen with multi-sampling.

    jollyjeffers
    jollyjeffers
    quick reply as it's past my bedtime...

    Quote:
    Does the demo, "The Project", have multi-sampling enabled?
    I think it does, but I don't have time to double-check it now as it takes several months to load [rolleyes].

    Quote:
    Umm..don't you have any games MR UBER GEEK?
    Games? What, you think I can waste time on such things when there are forum posts to be replied to...?!

    Only games I'm playing are on Windows Vista at the moment - C&C3 won't run on Windows XP.

    Jack
    <hr align="left" width="25%" />
    Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ |
    circlesoft
    circlesoft
    Well look who it is!

    Quote:
    There's no way to work around this with wxWidgets, since it's a huge dependency, but I'll look into incorporating the headers I use from boost into the source tree.

    Or you could reundisincorporate them back out of the source tree and use something worthwhile [wink]

    Anyhow, I still have an XP system so I'll test soon. You wouldn't believe how many people come around looking for this overlay stuff.
    Muhammad Haggag
    Muhammad Haggag
    Quote:
    Original post by circlesoft
    Quote:
    There's no way to work around this with wxWidgets, since it's a huge dependency, but I'll look into incorporating the headers I use from boost into the source tree.

    Or you could reundisincorporate them back out of the source tree and use something worthwhile [wink]

    Go back to your C with classes, heathen. I'll keep my C++ [wink]

    Quote:
    Anyhow, I still have an XP system so I'll test soon. You wouldn't believe how many people come around looking for this overlay stuff.

    If you have no results to show, why are you posting in the first place? Remember, I know where you live. So get on with it.

    aeoth
    aeoth
    Quote:
    It's not entirely clear what's going on with #2, perhaps it has to do with multisampling or some setting used by the games by default.


    Windows Vista, NVIDIA 7900GT

    DX9
    In World of Warcraft, changing multisampling to 1x (or, I guess, off), made it display. Any other value, and yup, the overlay was hidden.

    In Lord of the Rings Online, it worked fine, although I couldn't see a specific multisampling setting.

    In C&C3 I couldn't get the overlay to show at all

    WMP worked fine.

    OpenGL
    Well, I really only had one to test...Frets on Fire.
    Confirming your third point, the overlay was hidden.

    I'd seen your C++/C# samples late last year, but I've only gotten around to looking into it today.
    Talk about great timing... ;)

    I suppose the 'worst' problem with this, from a Vista users point of view, is the disabling of Aero once the overlay is initalised (and isn't restored until the sample program is closed)

    I don't know if this can be 'fixed', or if really matters too much.
    You can probably just fire DwmEnableComposition() from DWMAPI.DLL, or something along those lines (And I guess check if it was enabled in the first place, using DwmIsCompositionEnabled()), inside any application using this.
    Muhammad Haggag
    Muhammad Haggag
    Thanks for the report.

    Quote:
    Original post by aeoth
    DX9
    In World of Warcraft, changing multisampling to 1x (or, I guess, off), made it display. Any other value, and yup, the overlay was hidden.

    In Lord of the Rings Online, it worked fine, although I couldn't see a specific multisampling setting.

    In C&C3 I couldn't get the overlay to show at all

    WMP worked fine.

    Yes, it seems to be a problem with multi-sampling on Vista. An XP tester reported that the overlay worked for him even with multisampling.

    Quote:
    OpenGL
    Well, I really only had one to test...Frets on Fire.
    Confirming your third point, the overlay was hidden.

    Yeah, seems like another Vista issue.

    Quote:
    I suppose the 'worst' problem with this, from a Vista users point of view, is the disabling of Aero once the overlay is initalised (and isn't restored until the sample program is closed)

    I don't know if this can be 'fixed', or if really matters too much.
    You can probably just fire DwmEnableComposition() from DWMAPI.DLL, or something along those lines (And I guess check if it was enabled in the first place, using DwmIsCompositionEnabled()), inside any application using this.

    Well, that's what I do--I check if composition is enabled, and if it is, I disable it when the overlay manager is created. Turning off composition turns off Aero.

    Programmer16
    Programmer16
    I'm using Windows XP and a 256MB ATI Radeon Sapphire X700 Pro. The overlay was there when I ran Oblivion, but it I didn't see it for either Diablo 2 or Baldur's Gate 2. I'll dig out a couple more games and let you know how it goes.
    kahuna42
    kahuna42
    any progress on the managed wrapper? or any clue if it could possibly be done directly in managed code? i looked at some of the stuff in OverlayManager, and since the DX9 managed docs have deprecated all of DirectDraw and only give minimal info, i didn't get very far.

    not trying to rush ya, but i've got existing managed code that i need to have work with an overlay, and i'm just wondering when i'll be able to work on it.
    kahuna42
    kahuna42
    in answer to my own question, yes, it's possible to do this entirely in managed code. it made more sense this morning when i looked at it again... maybe it was just a lack of sleep.

    next question - i need to draw on the overlay without overwriting everything underneath. I've tried creating a bitmap, drawing to it, and blitting, but of course the given blit methods don't handle transparency. any suggestions on how to keep the overlay transparent? using a color key would be OK, but i haven't figured out where to set one so that it keeps what shows up on screen transparent except for what i drew (text for example).

    note: in my case, i am using nvidia, therefore one of the YUV color models (although i need it to work regardless of color model). i tried making a surface out of an RGB bitmap and using destinationOverlay.DrawFast to draw it, but it threw an exception - i'm assuming it doesn't translate between color spaces that way.
    Headkaze
    Headkaze
    Yes your right you can get overlays working in managed code alone, here is how I did it. I have an NVidia card to, so I had to do a few things differently to get it to work on all my video cards.

    - I attempt to create the overlay surface using Bpp16555, Bpp16565, Bpp32, Bpp24 and YUY2 in that order. As each one fails I try the next. On NVidia cards it will keep failing until it reaches the YUY2 bit format.

    - I have my image in a surface that I Draw (blt) onto the overlay surface in the RenderCallback delegate. If you try to use GetDc() from the overlay surface in the callback it will fail for the YUY2 bit format. Also using the Draw technique is faster, doesn't require GDI and works for all formats. It also takes care of the format conversion for you, so no need to do that manually (which is slow as well). I'm not sure why Mahammad does the format conversion manually in his library.

    - Now to your problem over using a color key. To use a color key you simply do the following in your Update() method which flips the overlay onto the primary surface.

    overlayFlags = DirectDraw.OverlayFlags.Show;if (caps.ColorKeyCaps.SourceOverlay){	DirectDraw.ColorKey key = new DirectDraw.ColorKey();	key.ColorSpaceHighValue = 0;	key.ColorSpaceLowValue = 0;	overlayEffects.SourceColorKey = key;	overlayFlags |= DirectDraw.OverlayFlags.Effects | DirectDraw.OverlayFlags.KeySourceOverride;}System.Drawing.Rectangle destRectangle = new System.Drawing.Rectangle(0, 0, overlayWidth, overlayHeight);overlaySurface.UpdateOverlay(overlaySurface, destRectangle, overlayFlags, overlayEffects);


    The problem is that NVidia cards don't seem to support hardware color keying. If you remove the check for caps.ColorKeyCaps.SourceOverlay you will get a NoColorKeyHardwareException error.

    On other hardware I tried, I removed the check and the color keying worked. But that was on a laptop. On an ATI card the color keying did not work either. Also using a color other than black (0) was problematic. Well actually I couldn't get any color to work other than black.

    So I think it boils down to the fact that you can't use color keying on NVidia cards which is a shame because it is a handy thing to have for an overlay. If you have any success please share with us on this forum.
    kahuna42
    kahuna42
    Could you share some of the code you used? I've ported Muhammad's blit routines, and if i use those, i can draw a bitmap directly onto the overlayBackSurface. However, no matter how I create another surface to try to use with overlayBackSurface.Draw, I get an exception because of an E_FAIL somewhere in Surface.DrawInternal. What I tried just now was:

    SurfaceDescription desc = new SurfaceDescription();
    Surface surface2 = new Surface(bitmap, desc, manager.Device);
    overlayBackSurface.Draw(surface2, DrawFlags.Wait);

    i've tried a more complete SurfaceDescription, with matching PixelFormat to the existing surface, and this also didn't work. also tried passing a rectangle where appropriate, which didn't help.

    As for your changes to the Update method - are those in place of the existing 'flip', or should that go in before the 'flip'?

    I really hope that the color keying can be made to work... without it, the whole overlay technique is pretty much useless for me. I'm wanting to overlay information on the game UI (Lord of the Rings Online) such as putting a GPS-like 'trail' on top of the mini-map/radar so those who are truly directionally challenged can get back out of an area by retracing their steps.

    as for generating said image... would it be better to prepare a bitmap of the overlay using System.Drawing.Graphics, or should I try to use the various DrawXYZ (circle, ellipse, etc) methods of Surface?
    Headkaze
    Headkaze
    Check out the MDX example from http://www.gamedev.net/community/forums/topic.asp?topic_id=367591

    Load your bitmap using...

    Bitmap bmpOverlay = (Bitmap)Bitmap.FromFile(Path.Combine(Application.StartupPath, "MyImage.png"));DirectDraw.SurfaceDescription surfaceDesc = new DirectDraw.SurfaceDescription();surfaceDesc.SurfaceCaps.OffScreenPlain = true;surfaceDesc.SurfaceCaps.VideoMemory = true;surfaceDesc.Width = bmpOverlay.Width;surfaceDesc.Height = bmpOverlay.Height;surface = new DirectDraw.Surface(bmpOverlay, surfaceDesc, device);


    The callback looks like this

    public static void RenderCallback(DirectDraw.Device device, DirectDraw.Surface overlaySurface){	try	{		Rectangle srcRect = new Rectangle(0, 0, Global.surface.SurfaceDescription.Width, Global.surface.SurfaceDescription.Height);		Rectangle destRect = new Rectangle(0, 0, overlaySurface.SurfaceDescription.Width, overlaySurface.SurfaceDescription.Height);		overlaySurface.Draw(destRect, Global.surface, srcRect, DirectDraw.DrawFlags.DoNotWait);	}	catch	{	}}


    My changes to the Update method are straight forward when you look at the MDX example above. Yes it goes after the flip and replaces the code there.

    Topic Locked

    This topic has been locked by a moderator. New replies are not allowed.

    Sign in to reply to this topic.