252ea7753293a025ce62e934ff0ab154a0561dcd
[blender-staging.git] / intern / ghost / intern / GHOST_DisplayManagerWin32.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file ghost/intern/GHOST_DisplayManagerWin32.cpp
29  *  \ingroup GHOST
30  *  \author     Maarten Gribnau
31  *  \date       September 21, 2001
32  */
33
34 #include "GHOST_DisplayManagerWin32.h"
35 #include "GHOST_Debug.h"
36
37 #undef _WIN32_WINNT
38 #define _WIN32_WINNT 0x501 // require Windows XP or newer
39 #define WIN32_LEAN_AND_MEAN
40 #include <windows.h>
41
42 // We do not support multiple monitors at the moment
43 #define COMPILE_MULTIMON_STUBS
44 #ifndef FREE_WINDOWS
45 #include <multimon.h>
46 #endif
47
48
49 GHOST_DisplayManagerWin32::GHOST_DisplayManagerWin32(void)
50 {
51 }
52
53
54 GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplays(GHOST_TUns8& numDisplays) const
55 {
56         numDisplays = ::GetSystemMetrics(SM_CMONITORS);
57         return numDisplays > 0 ? GHOST_kSuccess : GHOST_kFailure;
58 }
59
60 static BOOL get_dd(DWORD d, DISPLAY_DEVICE *dd)
61 {
62         dd->cb = sizeof(DISPLAY_DEVICE);
63         return ::EnumDisplayDevices(NULL, d, dd, 0);
64 }
65
66 /*
67  * When you call EnumDisplaySettings with iModeNum set to zero, the operating system 
68  * initializes and caches information about the display device. When you call 
69  * EnumDisplaySettings with iModeNum set to a non-zero value, the function returns 
70  * the information that was cached the last time the function was called with iModeNum
71  * set to zero. 
72  */
73 GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const
74 {
75         DISPLAY_DEVICE display_device;
76         if (!get_dd(display, &display_device)) return GHOST_kFailure;
77
78         numSettings = 0;
79         DEVMODE dm;
80         while (::EnumDisplaySettings(display_device.DeviceName, numSettings, &dm)) {
81                 numSettings++;
82         }
83         return GHOST_kSuccess;
84 }
85
86
87 GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const
88 {
89         DISPLAY_DEVICE display_device;
90         if (!get_dd(display, &display_device)) return GHOST_kFailure;
91
92         GHOST_TSuccess success;
93         DEVMODE dm;
94         if (::EnumDisplaySettings(display_device.DeviceName, index, &dm)) {
95 #ifdef GHOST_DEBUG
96                 printf("display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency);
97 #endif // GHOST_DEBUG
98                 setting.xPixels     = dm.dmPelsWidth;
99                 setting.yPixels     = dm.dmPelsHeight;
100                 setting.bpp         = dm.dmBitsPerPel;
101                 /* When you call the EnumDisplaySettings function, the dmDisplayFrequency member
102                  * may return with the value 0 or 1. These values represent the display hardware's
103                  * default refresh rate. This default rate is typically set by switches on a display 
104                  * card or computer motherboard, or by a configuration program that does not use 
105                  * Win32 display functions such as ChangeDisplaySettings. 
106                  */
107                 /* First, we tried to explicitly set the frequency to 60 if EnumDisplaySettings
108                  * returned 0 or 1 but this doesn't work since later on an exact match will
109                  * be searched. And this will never happen if we change it to 60. Now we rely
110                  * on the default h/w setting.
111                  */
112                 setting.frequency = dm.dmDisplayFrequency;
113                 success = GHOST_kSuccess;
114         }
115         else {
116                 success = GHOST_kFailure;
117         }
118         return success;
119 }
120
121
122 GHOST_TSuccess GHOST_DisplayManagerWin32::getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const
123 {
124         return getDisplaySetting(display, ENUM_CURRENT_SETTINGS, setting);
125 }
126
127
128 GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting)
129 {
130         DISPLAY_DEVICE display_device;
131         if (!get_dd(display, &display_device)) return GHOST_kFailure;
132
133         GHOST_DisplaySetting match;
134         findMatch(display, setting, match);
135         DEVMODE dm;
136         int i = 0;
137         while (::EnumDisplaySettings(display_device.DeviceName, i++, &dm)) {
138                 if ((dm.dmBitsPerPel       == match.bpp    ) &&
139                     (dm.dmPelsWidth        == match.xPixels) &&
140                     (dm.dmPelsHeight       == match.yPixels) &&
141                     (dm.dmDisplayFrequency == match.frequency))
142                 {
143                         break;
144                 }
145         }
146         /*
147          * dm.dmBitsPerPel = match.bpp;
148          * dm.dmPelsWidth = match.xPixels;
149          * dm.dmPelsHeight = match.yPixels;
150          * dm.dmDisplayFrequency = match.frequency;
151          * dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
152          * dm.dmSize = sizeof(DEVMODE);
153          * dm.dmDriverExtra = 0;
154          */
155 #ifdef GHOST_DEBUG
156         printf("display change: Requested settings:\n");
157         printf("  dmBitsPerPel=%d\n", dm.dmBitsPerPel);
158         printf("  dmPelsWidth=%d\n", dm.dmPelsWidth);
159         printf("  dmPelsHeight=%d\n", dm.dmPelsHeight);
160         printf("  dmDisplayFrequency=%d\n", dm.dmDisplayFrequency);
161 #endif // GHOST_DEBUG
162
163         LONG status = ::ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
164 #ifdef GHOST_DEBUG
165         switch (status) {
166                 case DISP_CHANGE_SUCCESSFUL:
167                         printf("display change: The settings change was successful.\n");
168                         break;
169                 case DISP_CHANGE_RESTART:
170                         printf("display change: The computer must be restarted in order for the graphics mode to work.\n");
171                         break;
172                 case DISP_CHANGE_BADFLAGS:
173                         printf("display change: An invalid set of flags was passed in.\n");
174                         break;
175                 case DISP_CHANGE_BADPARAM:
176                         printf("display change: An invalid parameter was passed in. "
177                                "This can include an invalid flag or combination of flags.\n");
178                         break;
179                 case DISP_CHANGE_FAILED:
180                         printf("display change: The display driver failed the specified graphics mode.\n");
181                         break;
182                 case DISP_CHANGE_BADMODE:
183                         printf("display change: The graphics mode is not supported.\n");
184                         break;
185                 case DISP_CHANGE_NOTUPDATED:
186                         printf("display change: Windows NT: Unable to write settings to the registry.\n");
187                         break;
188                 default:
189                         printf("display change: Return value invalid\n");
190                         break;
191         }
192 #endif // GHOST_DEBUG
193         return status == DISP_CHANGE_SUCCESSFUL ? GHOST_kSuccess : GHOST_kFailure;
194 }