Dual Monitors ... The Answers + Working Code
Moderator: InsideQC Admins
7 posts
• Page 1 of 1
Dual Monitors ... The Answers + Working Code
Now, as far as I know, nobody on the internet has had any level of success with Windows + OpenGL and dual monitors.
I have 2 working solutions to this capability. One solution deals with the classic problem trying to do this (which I have worked around.)
I'll be walking through those and documenting within the next 1 hour or 2.
[I guess with Direct3D this is a breeze, but OpenGL it isn't so easy.].
I have 2 working solutions to this capability. One solution deals with the classic problem trying to do this (which I have worked around.)
I'll be walking through those and documenting within the next 1 hour or 2.
[I guess with Direct3D this is a breeze, but OpenGL it isn't so easy.].
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
First, I'm going to describe how Windows handles dual monitors [or more than 2 monitors].
Using EnumDisplayDevices, you get can the list of the "display devices" (some of which are monitors, but not all) and after filtering out the non-monitors, you have this data.
1. Display name
2. x origin
3. y origin
4. display pixel width
5. display pixel height
The primary monitor is the display device with x/y origin 0, 0.
So the data may look like this
If you want to create a window on DISPLAY2, use coordinates 1280,0.
If you want to change the primary display, you first change the display settings on what you want to be the secondary monitor, like if switching the above you'd do ...
DISPLAY1 ---> x, y = 1400, 0
And then set the new primary monitor to 0,0 ....
DISPLAY2 ---> x, y = 0,0
I have a dual monitors on my desktop with a GeForce 5200 FX and an Intel display adapter. If I try to setup a window on the secondary monitor without forcing it to be the primary monitor, I get nothing but a white screen ... so for mixed monitor video cards you have to force the secondary display to the primary.
For same display adapter dual monitors ... like my Vista laptop with a dual monitor capable GeForce Go, I can setup the monitor on either window with no problem and full open GL acceleration.
ChangeDisplaySettings does accept a "Device Name" to specifiy which monitor to set a fullscreen mode and combined with doing a CreateWindow in the correct X/Y space, you can do a fullscreen window on a secondary monitor *IN* in a same-video-adapter type of situation like the above mentioned GeForce Go dual monitor supporting laptop scenario.
Using EnumDisplayDevices, you get can the list of the "display devices" (some of which are monitors, but not all) and after filtering out the non-monitors, you have this data.
1. Display name
2. x origin
3. y origin
4. display pixel width
5. display pixel height
The primary monitor is the display device with x/y origin 0, 0.
So the data may look like this
- Code: Select all
Device Name | X Origin | Y Origin | Pixel Width | Pixel Height
DISPLAY1 0 0 1280 1024
DISPLAY2 1280 0 1400 900
If you want to create a window on DISPLAY2, use coordinates 1280,0.
If you want to change the primary display, you first change the display settings on what you want to be the secondary monitor, like if switching the above you'd do ...
DISPLAY1 ---> x, y = 1400, 0
And then set the new primary monitor to 0,0 ....
DISPLAY2 ---> x, y = 0,0
I have a dual monitors on my desktop with a GeForce 5200 FX and an Intel display adapter. If I try to setup a window on the secondary monitor without forcing it to be the primary monitor, I get nothing but a white screen ... so for mixed monitor video cards you have to force the secondary display to the primary.
For same display adapter dual monitors ... like my Vista laptop with a dual monitor capable GeForce Go, I can setup the monitor on either window with no problem and full open GL acceleration.
ChangeDisplaySettings does accept a "Device Name" to specifiy which monitor to set a fullscreen mode and combined with doing a CreateWindow in the correct X/Y space, you can do a fullscreen window on a secondary monitor *IN* in a same-video-adapter type of situation like the above mentioned GeForce Go dual monitor supporting laptop scenario.
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
I havent gotten the Fullscreen to work properly but starting/switching to windowed mode then dragging the window to the other monitor works.
bulk of the windowed code
in Sys_Init
I spent a day working on this a couple years back, might be time to try again... Thanks for the info.
bulk of the windowed code
- Code: Select all
HMONITOR prevMonitor; // The previous monitor the window was on before getting destroyed.
MONITORINFOEX prevMonInfo; // Information about the previous monitor the window was on before getting destroyed.
HMONITOR hCurrMon;
MONITORINFOEX currMonInfo;
// Finds out what monitor the window is currently on.
HMONITOR VID_GetCurrentMonitor()
{
return MonitorFromWindow(mainwindow, MONITOR_DEFAULTTOPRIMARY);
}
// Finds out info about the current monitor.
MONITORINFOEX VID_GetCurrentMonitorInfo(HMONITOR monitor)
{
MONITORINFOEX inf;
memset(&inf, 0, sizeof(MONITORINFOEX));
inf.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(monitor, (LPMONITORINFO)&inf);
return inf;
}
in Sys_Init
- Code: Select all
hCurrMon = prevMonitor = VID_GetCurrentMonitor();
currMonInfo = prevMonInfo = VID_GetCurrentMonitorInfo(prevMonitor);
- Code: Select all
void VID_UpdateWindowStatus (void)
{
RECT monitor_rect;
// Get the current monitor and info about it.
hCurrMon = VID_GetCurrentMonitor();
currMonInfo = VID_GetCurrentMonitorInfo(hCurrMon);
monitor_rect = currMonInfo.rcMonitor;
GetWindowRect( mainwindow, &window_rect);
if (window_rect.left < monitor_rect.left)
window_rect.left = monitor_rect.left;
if (window_rect.top < monitor_rect.top)
window_rect.top = monitor_rect.top;
if (window_rect.right >= monitor_rect.right)
window_rect.right = monitor_rect.right - 1;
if (window_rect.bottom >= monitor_rect.bottom)
window_rect.bottom = monitor_rect.bottom - 1;
window_center_x = (window_rect.right + window_rect.left) / 2;
window_center_y = (window_rect.top + window_rect.bottom) / 2;
window_rect = monitor_rect;//R00k
IN_UpdateClipCursor ();
}
I spent a day working on this a couple years back, might be time to try again... Thanks for the info.
- r00k
- Posts: 1110
- Joined: Sat Nov 13, 2004 10:39 pm
It was like jamming toothpicks into my eyes, but the vague version goes like this:
Cheat Version:
The Cheat Version works 100%. Think of it like this, when Quake goes fullscreen, it changes the display mode. But when you quit Quake, it resets it. Since multiple different video cards doesn't play nice with OpenGL as it is implemented in Windows, just switch the primary monitor and restore it upon exit.
1. Use EnumDisplayDevices to populate a list of monitors. One option is just to stop at 2 monitors as I don't have a 3 or monitor system to test with anyway.
2. Set the secondary monitor to position 0,0 after setting the [formerly] primary monitor position to (secondary_monitor_pixel_width_x, 0).
3. Kapowie ... the rest of Quake works as-is. Even if using, like I do, something like MH's Direct3D wrapper.
4. In shutdown, restore the original settings.
Obviously, 2 different Quake .exes cannot run on 2 separate monitors in this scenario.
"Real Version":
1. Get the monitor information like #1 in the above.
2. Do CreateWindowEx using the secondary monitor _origin_x and origin_y as the top right. GetDC and the rest work as expected.
3. ChangeDisplaySettings accepts as the first parameter the DisplayDevice. Set this DisplayDevice to be the secondary monitor name.
4. From this point forward, everything else works the same. Except if you literally have 2 video cards like my desktop, Windows apparently is not-prepared to handle this and it results in an uber fail with a black screen or white screen [depending on how you choose to clear the screen after initializing the window with PalBlt or what not]. But it does work with a single display adapter, like my laptop, which supports multiple monitors via the single display adapter.
Extra note: Generally, you have to use Microsoft Visual Studio 2008 or later (maybe older Visual Studio .NET versions work, but not MSVC6 ... unless you have Windows 2003 server SP1 SDK, which isn't available on the internets anymore). In some ways, I over-dedicated time to solve this issue, but I'm very stubborn and kept at it until I achieved what I considered an acceptable solution. I didn't like the idea of sitting at the doorstep of the solution without being able to open the actual effin door.
Cheat Version:
The Cheat Version works 100%. Think of it like this, when Quake goes fullscreen, it changes the display mode. But when you quit Quake, it resets it. Since multiple different video cards doesn't play nice with OpenGL as it is implemented in Windows, just switch the primary monitor and restore it upon exit.
1. Use EnumDisplayDevices to populate a list of monitors. One option is just to stop at 2 monitors as I don't have a 3 or monitor system to test with anyway.
2. Set the secondary monitor to position 0,0 after setting the [formerly] primary monitor position to (secondary_monitor_pixel_width_x, 0).
3. Kapowie ... the rest of Quake works as-is. Even if using, like I do, something like MH's Direct3D wrapper.
4. In shutdown, restore the original settings.
Obviously, 2 different Quake .exes cannot run on 2 separate monitors in this scenario.
"Real Version":
1. Get the monitor information like #1 in the above.
2. Do CreateWindowEx using the secondary monitor _origin_x and origin_y as the top right. GetDC and the rest work as expected.
3. ChangeDisplaySettings accepts as the first parameter the DisplayDevice. Set this DisplayDevice to be the secondary monitor name.
4. From this point forward, everything else works the same. Except if you literally have 2 video cards like my desktop, Windows apparently is not-prepared to handle this and it results in an uber fail with a black screen or white screen [depending on how you choose to clear the screen after initializing the window with PalBlt or what not]. But it does work with a single display adapter, like my laptop, which supports multiple monitors via the single display adapter.
Extra note: Generally, you have to use Microsoft Visual Studio 2008 or later (maybe older Visual Studio .NET versions work, but not MSVC6 ... unless you have Windows 2003 server SP1 SDK, which isn't available on the internets anymore). In some ways, I over-dedicated time to solve this issue, but I'm very stubborn and kept at it until I achieved what I considered an acceptable solution. I didn't like the idea of sitting at the doorstep of the solution without being able to open the actual effin door.
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
Add: the pixel format descriptor will tell you if you have hardware acceleration or not, as I understand it. So the lack of hardware acceleration problem can at least be detected and maybe you warn the user if monitor #2 isn't going to natively get hardware acceleration.
I may take a stab at true dual monitor support with that little puzzle piece available. By my guess is that this will not be anytime soon since I really only personally care about dual monitor support to quickly and conveniently do engine testing against different video cards and the fake method lets me do that efficiently.
I may take a stab at true dual monitor support with that little puzzle piece available. By my guess is that this will not be anytime soon since I really only personally care about dual monitor support to quickly and conveniently do engine testing against different video cards and the fake method lets me do that efficiently.
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
7 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 1 guest