Hi
This snippet gives you a good string identifier for each adapter
Regards
Biterider
This snippet gives you a good string identifier for each adapter
mov edi, $ICall(.pID3D::IDirect3D9.GetAdapterCount)
xor ebx, ebx
.while ebx < edi
ICall .pID3D::IDirect3D9.GetAdapterIdentifier, ebx, 0, addr AdapterInfo
@invoke wsprintf, addr bBuffer, "%u - %s", ebx, addr AdapterInfo.Description
invoke SendDlgItemMessage, .hWnd, IDC_DXS_ADAPTERS, CB_ADDSTRING, 0, addr bBuffer
...
inc ebx
.endw
Regards
Biterider
Thanks Biterider, but that is what I'm doing... The problem ti_mo_n describes is when you have one adapter, with two outputs. D3D9 doesn't really have a distinction between adapter and display, so it enumerates the same adapter twice, so you get the same description. The difference is the monitor attached, but I don't know how to get that info. It seems they 'forgot' this in the API :)
In D3D10 you get one adapter, with two displays. The only problem I have there is that it returns \\DISPLAY1 rather than the actual device name. But I suppose if you have \\DISPLAY1, you could get the actual name from the registry somehow, with the SetupAPI or something. With D3D9 I have no idea what to do.
In D3D10 you get one adapter, with two displays. The only problem I have there is that it returns \\DISPLAY1 rather than the actual device name. But I suppose if you have \\DISPLAY1, you could get the actual name from the registry somehow, with the SetupAPI or something. With D3D9 I have no idea what to do.
Tried prior to the DX update, nothing. After, nothing... methinks some error-handling is in order. ;)
AMD 4000+ Dual, WinXP Pro x64 SP2, GeForce 8600GTS, dual monitors.
AMD 4000+ Dual, WinXP Pro x64 SP2, GeForce 8600GTS, dual monitors.
Tried prior to the DX update, nothing. After, nothing... methinks some error-handling is in order. ;)
AMD 4000+ Dual, WinXP Pro x64 SP2, GeForce 8600GTS, dual monitors.
Thing is, I wasn't really planning on doing any work on XP/D3D9 anymore :P
You should. Majority of people don't have Vista and wait for Windows 7 (or don't plan to switch at all in the nearest furute). And even after Windows 7 is out there will still be many users using XP. D3D9 isn't going to die very soon :)
About monitor: I don't remember exactly (and for some strange reason I can't find my app where I do it -- Murphy doesn't like me) but from what I do remember is that you have to use D3D9->GetAdapterMonitor and Winapi's GetMonitorInfo and EnumDisplayMonitors. Then you have to play correctly with RECT structures, IIRC. The names you get aren't guaranteed to be real names of outputs but at least they give users some way to distinguish between the options they get.
About monitor: I don't remember exactly (and for some strange reason I can't find my app where I do it -- Murphy doesn't like me) but from what I do remember is that you have to use D3D9->GetAdapterMonitor and Winapi's GetMonitorInfo and EnumDisplayMonitors. Then you have to play correctly with RECT structures, IIRC. The names you get aren't guaranteed to be real names of outputs but at least they give users some way to distinguish between the options they get.
You should. Majority of people don't have Vista and wait for Windows 7. And even after Windows 7 is out there will still be many users using XP. D3D9 isn't going to die very soon :)
Problem is, if we don't stop supporting them, we'll NEVER get rid of XP/DX9.
I have to develop and test my code for both DX9 and DX10, and test it on XP and Vista. The differences are just too large, and it takes too much effort.
I prefer spending all my time on DX10/11. The DX9 code is pretty old by now, so it should work on most systems anyway, haven't really had troubles in years. I wasn't planning on doing much work on it anymore.
About monitor: I don't remember exactly (and for some strange reason I can't find my app where I do it -- Murphy doesn't like me) but from what I do remember is that you have to use D3D9->GetAdapterMonitor and Winapi's GetMonitorInfo and EnumDisplayMonitors. Then you have to play correctly with RECT structures, IIRC. The names you get aren't guaranteed to be real names of outputs but at least they give users some way to distinguish between the options they get.
Thanks, I'll see if I can make that work for me :)
I know that rendering stops when it's minimized, but it should start again when it's resized to anything else...
It works in windowed mode but not in fullscreen. When in fullscreen mode, minimizing and then maximizing stops the rendering.
------------
I have found the app. I have also attached the image showing how it looks like on my machine.
Here is the relevant code:
INT __cdecl _tmain(INT argc, _TCHAR* argv[]) {
union {
MONITORINFOEX mie;
TCHAR dummy[(sizeof(MONITORINFOEX)+1)];
};
IDirect3D9 *d3d9;
UINT adcnt, i;
HMONITOR hm;
if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION))) {
_tprintf(TEXT("Direct3DCreate9 failed!\n"));
return 1;
}
if ((adcnt = d3d9->GetAdapterCount())) {
for (i = 0; i < adcnt; i++) {
_tprintf(TEXT("adapter %u: "), i);
if ((hm = d3d9->GetAdapterMonitor(i))) {
mie.cbSize = sizeof(mie);
dummy = 0;
if (GetMonitorInfo(hm, &mie)) {
_tprintf(TEXT("%s"), &mie.szDevice);
if (mie.dwFlags & MONITORINFOF_PRIMARY) {
_tprintf(TEXT(" (PRIMARY)"));
}
_tprintf(TEXT("\n"));
}
else {
_tprintf(TEXT("(GetMonitorInfo failed!)\n"));
}
}
else {
_tprintf(TEXT("<null>\n"));
}
}
}
d3d9->Release();
d3d9 = NULL;
return 0;
}
Note that the primary display doesn't have to be the first one.
Ah okay...
What I was wondering... how can you get the names of the actual displays as you see them in Control Panel or Device Manager for example?
Eg, in the Display Settings I actually see "Samsung 770P on GeForce 8800GTS..."
I wonder how I can get from "\\DISPLAY1" and such to the actual devicename. I think that's the best possible information for letting a user decide which display to use.
What I was wondering... how can you get the names of the actual displays as you see them in Control Panel or Device Manager for example?
Eg, in the Display Settings I actually see "Samsung 770P on GeForce 8800GTS..."
I wonder how I can get from "\\DISPLAY1" and such to the actual devicename. I think that's the best possible information for letting a user decide which display to use.
I guess your only option is WMI but this is completely black magic to me. I've seen some examples on the Internet showing nice monitor names retrieved using WMI.
I have done some research into the subject. There is an easy way to get useful info about all display outputs in the system. You can use Nvidia Control Panel API. Unfortunately it works only with NVIDIA drivers (but I guess ATI has a similar library). Another problem is that you only get only 64-bit version of the dll with 64-bit drivers and only 32-bit version with 32-bit ones. So on 64-bit system (with 64-bit drivers) a 32-bit app can't use it. It's possible to work this around by having a dummy 64-bit process and communicating with it via any IPC mechanism.
A sample and pdf can be downloaded here: NVIDIA Control Panel API.
I have also attached my own example.
A sample and pdf can be downloaded here: NVIDIA Control Panel API.
I have also attached my own example.
Thanks, but vendor-specific solutions are exactly what I want to avoid.
I think the answer lies somewhere in this part of the registry:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\DISPLAY
That's where the known monitors are listed, with their descriptive names. Now I have to somehow relate that to the DX info.
I think the answer lies somewhere in this part of the registry:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\DISPLAY
That's where the known monitors are listed, with their descriptive names. Now I have to somehow relate that to the DX info.
It requires monitor drivers to be installed and it won't tell you anything about TVs and physical resolutions, etc. Since 2 vendors control, like, 99% of the graphics card market, I guess it's not a big problem to use their APIs ^^
It requires monitor drivers to be installed and it won't tell you anything about TVs and physical resolutions, etc. Since 2 vendors control, like, 99% of the graphics card market, I guess it's not a big problem to use their APIs ^^
Well, I often develop on my laptop, with an Intel graphics chip :)
If monitor drivers aren't installed, I guess it's fine to just have 'default monitor' or just '\\DISPLAY1' or such. But in most cases, drivers are installed, because lots of them are either bundled with Windows, or available on Update.
Intel has the biggest marketshare, and will get even bigger when Larrabee is out. And then there are S3 and Matrox. I want to support them all.
Oh, I was talking about desktops. So, well, You can always write this like I did in the application I attached earlier: It uses Nvidia CPL and (in case of error) defaults to "\\.\DisplayX". I personally prefer to know more than less about the hardware my app is running on ^^
Well, I've found something...
With EnumDisplayDevices() you can get the monitor name. Normally you'd use it to enumerate by index. Then it will just give you all \\.\DISPLAYx device names and corresponding adapter names.
However, if you pass the device name, and pass index 0, it will instead give you more info about that device, including the actual monitor name in the DeviceString, rather than the adapter name.
So what I do now is simple: I first get the hMonitor, then use GetMonitorInfo() to get the \\.\DISPLAYx device name, then use EnumDisplayDevices() to resolve it to the actual monitor name.
Works for both D3D9 and D3D10/11, because with DXGI you also get the \\.\DISPLAYx name of the output, which you'll plug into EnumDisplayDevices().
With EnumDisplayDevices() you can get the monitor name. Normally you'd use it to enumerate by index. Then it will just give you all \\.\DISPLAYx device names and corresponding adapter names.
However, if you pass the device name, and pass index 0, it will instead give you more info about that device, including the actual monitor name in the DeviceString, rather than the adapter name.
So what I do now is simple: I first get the hMonitor, then use GetMonitorInfo() to get the \\.\DISPLAYx device name, then use EnumDisplayDevices() to resolve it to the actual monitor name.
Works for both D3D9 and D3D10/11, because with DXGI you also get the \\.\DISPLAYx name of the output, which you'll plug into EnumDisplayDevices().
Nice ^^ I'll see if it works with TVs.
Nice ^^ I'll see if it works with TVs.
It should return the exact same monitor names as what you see in the display properties in Control Panel (the regular Windows control panel that is).
My TV uses standard s-video, so I only get "Generic P&P monitor" or something.
I suppose if your TV has a VGA, DVI or HDMI connector, it can use the DDC protocol to identify itself, and have Windows automatically install the proper .inf file for the monitor, to give it a descriptive name.
So I don't think there's any way that a hardware-specific solution would get more info than standard Windows.
From what I see, Windows doesn't query for physical resolution (in case of Digital Flat Panels) or optimal resolution (in case of CRTs).
1) It shows 2 exactly same strings for 2 different display outputs (I have 1 monitor and 1 HDTV attached to a GeForce 9600 GT -- see attached image). You should enumerate available monitors attached to the selected adapter and include their names in the selection strings.
This is solved now, with the name that EnumDisplayDevices() displays.
2) Minimizing then maximizing stops the rendering (displays black screen).
I've had a small look at this problem, and it seems to be specifically related to DX9 and multiple displays.
In DX10, the rendering stops when the window loses focus. This is by design (originally I wrote the code for a single display, and losing focus meant that you alt-tabbed away from the application, at which point I didn't want my application to hog the CPU. Alt-tabbing back into the application would bring it back to life). If the window regains focus, it continues rendering again.
In DX9 however, it seems that there's more going on. If I so much as click on the desktop on the other monitor, the window loses its fullscreen state and goes back to windowed mode. It doesn't know how to recover from this situation, because it should never happen (it doesn't, on a single display. The window is still 'fullscreen', even though it's not visible).
In short, I don't know what causes it, or how to fix it. There is code in my application to automatically reset the device when required. This is why resizing and alt-enter to switch between fullscreen and windowed mode just works. But somehow it doesn't recover from this situation.
I don't feel like wasting more time on it, because it only happens in DX9. I want to concentrate on DX11 from now on, DX9 is only there for legacy support and for that it's 'good enough' right now, the problem can easily be avoided. But if someone knows a fix, I might implement it.
3) There is no acpect-ratio compensation. The ring is elliptic at 16:9. It would be even more elliptic at 2.39:1.
Solved, the aspect-ratio fields in the initialization dialog are now used to create a perspective matrix.
Can I test it? ^^