5

When using CachedBitmaps in GDIPlus, there is graphical corruption if Windows video "Hardware Acceleration" is lowered too much - such that DirectDraw is disabled:

enter image description here

There are six levels of hardware acceleration:

  • Disable all accelerations
  • Disable all but basic accelerations. (Default on server machines)
  • Disable all DirectDraw and Direct3D accelerations, as well as all cursor and advanced accelerations
  • Disable all cursor and advanced drawing accelerations
  • Disable cursor and bitmap accelerations
  • All accelerations are enabled (Default on desktop machines)

If DirectDraw is disabled, then using DrawCachedBitmap in GDI+ will result in graphical corruption. It's easy enough for me to use the slower DrawImage() API if DirectDraw is not enabled - but i have to be able to detect that DirectDraw is disabled.

How can i programatically check if DirectDraw is enabled?


The question is: How does dxdiag do this:

alt text

See also

KB191660 - DirectDraw or Direct3D option is unavailable (archive)

Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
  • Good question. I found nothing in GetSystemMetrics, SystemParametersInfo or the (unexisting?) DirectDraw reference. As you know, DirectDraw is deprecated. – Andreas Rejbrand May 28 '10 at 17:16
  • i'm not actually using DirectDraw, so i'm unaffected if it is disabled. On the other hand i can't dictate what underlying technology GDIPlus uses. And the only reason i say "Direct Draw" is because the slider option that first causes problems mentions "DirectDraw and Direct3D", and i assume that GDI+ isn't using Direct3D - leaving DirectDraw. – Ian Boyd May 28 '10 at 17:37
  • @Andreas Rejbrand: i see what you mean about the DirectDraw documentation - it's as though DirectDraw never existed on the desktop. :\ – Ian Boyd May 28 '10 at 20:48
  • sounds like a video driver bug. also ms probably hasn't made an offical api for such a thing. if you want a dirty solution use procmon to identify the registry key used to store this setting – SteelBytes Aug 25 '10 at 11:09
  • 1
    @steelbytes If it is a driver bug, it's one that existed in every video card driver ever made for every operating system ever made – Ian Boyd Nov 12 '10 at 18:09
  • Looks like Stackoverflow will force accept an incorrect answer. When i get around to duplicating the question i'll update the question with the link. – Ian Boyd Nov 18 '10 at 20:22
  • 1
    It won't force except, it'll only award the bounty(and only to an answer with 2 or more upvotes). Down voting all our answers was pretty lame. We're trying to help you here and none of the information we provided was 'not helpful'. Good luck. – rwilliams Nov 18 '10 at 20:33

3 Answers3

4

If you download the latest DirectX SDK (I'm sure older sdk's have similar examples) there is an example of querying DXDIAG info.

The example is located at (SDK Root)\Samples\C++\Misc\DxDiagReport

In dxdiaginfo.cpp methods of note

CDxDiagInfo::CDxDiagInfo
CDxDiagInfo::Init
CDxDiagInfo::QueryDxDiagViaDll    
CDxDiagInfo::GetDisplayInfo

If you run the program it ouputs a giant list of values. I think the value you're interested in is pDisplayInfo->m_szDDStatusEnglish

rwilliams
  • 21,188
  • 6
  • 49
  • 55
  • Unfortunately the class required `CLSID_DxDiagProvider` is not available on Windows 2000. Just as well; `IID_IDxDiagProvider` is very slow in gathering information - not something suitable for production code. – Ian Boyd Nov 18 '10 at 19:37
  • DXDIAG doesn't exactly start instantly either. And if you want documented, you got it. (If you want to support Windows 2000, you should use the DDraw method above, since Win2K's DX support caps out at one that definitely has DDraw as part of it. Presumably just try it anyway if DXDIAG support isn't present, might as well, DDraw will be around for a while yet.) –  Nov 19 '10 at 13:28
  • Well GDI+ still carries a dependency on ddraw, which is the basis of WinForms. – Ian Boyd Nov 19 '10 at 16:26
0

You could check the registry for the acceleration slider value.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Video\{'some hex string'}\0000\Acceleration.Level

You're probably going to have to loop through all the folders in Video as there are generally more than one entry.

Acceleration.Level Values

  • 5 Disable all accelerations
  • 4 Disable all but basic accelerations. (Default on server machines)
  • 3 Disable all DirectDraw and Direct3D accelerations, as well as all cursor and advanced accelerations
  • 2 Disable all cursor and advanced drawing accelerations
  • 1 Disable cursor and bitmap accelerations
  • 0 All accelerations are enabled (Default on desktop machines)

Update:

Here's an older thread about programatically changing/checking the acceleration level. http://www.autoitscript.com/forum/topic/61185-hardware-acceleration/

rwilliams
  • 21,188
  • 6
  • 49
  • 55
  • i guess a real answer will have to address what the slider does. A slider at full doesn't mean that DirectDraw's enabled. And all the way at minimum doesn't mean that DirectDraw's necessarily disabled. – Ian Boyd Nov 14 '10 at 15:53
  • Windows 7, where there is no slider. – Ian Boyd Nov 18 '10 at 20:20
  • @Ian Boyd: There is no slider because your display drivers are overriding it. The registry value is still accurate. I got you this information testing on Windows 7. – rwilliams Nov 18 '10 at 20:31
0

You could query a IDirectDraw interface and see what it does. I assume it will fail if hardware acceleration is turned off, but you might want to test GetCaps() or TestCooperativeLevel().

LPDIRECTDRAW lpdd7 = NULL; // DirectDraw 7.0

// first initialize COM, this will load the COM libraries
// if they aren't already loaded
if (FAILED(CoInitialize(NULL)))
   {
   // error
   } // end if

// Create the DirectDraw object by using the
// CoCreateInstance() function
if (FAILED(CoCreateInstance(&CLSID_DirectDraw,
                         NULL, CLSCTX_ALL,
                         &IID_IDirectDraw7,
                         &lpdd7)))
   {
   // error
   }


// now before using the DirectDraw object, it must
// be initialized using the initialize method

if (FAILED(IDirectDraw7_Initialize(lpdd7, NULL)))
{
    // error
}

lpdd7->Release();
lpdd7 = NULL; // set to NULL for safety

// now that we're done with COM, uninitialize it
CoUninitialize();

Unfortunately the DirectDraw docs are no longer included in the SDKs. You might need an older version to get the samples and header files.

msteiger
  • 2,024
  • 16
  • 22
  • A call to `IDirectDraw.Initialize` always fails, whether the slider is turned down or not. There is no documentation, so i can't determine what the `Initialize` method is used for. Also, since DirectDraw is no longer documented, this answer is by definition not a documented way to check if direct draw is available. – Ian Boyd Nov 18 '10 at 20:20
  • DDraw still works fine with the latest DirectX SDK; the full set of libraries and headers are provided. Even x64 versions. (You probably want to be using it from C/C++, though.) None of it will be going away for a while yet, any more than any other part of the Windows API. This is almost certainly the right answer, and I bet it's pretty much what DXDIAG does, followed by a check of the `DDCAPS_NOHARDWARE` flag - though I didn't use IDA Pro to check. (P.S. http://www.megaupload.com/?d=Y01BRYFX - get it quick.) –  Nov 19 '10 at 13:24
  • I ran out of edit time. What I mean is, this is almost certainly the right answer, if you are sure that checking for availability of DirectDraw acceleration is the right thing to check for. (That is, you're sure the dialog isn't twiddling some other setting as well.) –  Nov 19 '10 at 13:32