comparison src/video/win32/SDL_win32modes.c @ 1895:c121d94672cb

SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author Sam Lantinga <slouken@libsdl.org>
date Mon, 10 Jul 2006 21:04:37 +0000
parents
children 83420da906a5
comparison
equal deleted inserted replaced
1894:c69cee13dd76 1895:c121d94672cb
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2006 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 #include "SDL_win32video.h"
25
26
27 /* FIXME: Each call to EnumDisplaySettings() takes about 6 ms on my laptop.
28 With 500 or so modes, this takes almost 3 seconds to run!
29 */
30
31 static SDL_bool
32 WIN_GetDisplayMode(LPCTSTR deviceName, DWORD index, SDL_DisplayMode * mode)
33 {
34 SDL_DisplayModeData *data;
35 DEVMODE devmode;
36 HDC hdc;
37
38 devmode.dmSize = sizeof(devmode);
39 devmode.dmDriverExtra = 0;
40 if (!EnumDisplaySettings(deviceName, index, &devmode)) {
41 return SDL_FALSE;
42 }
43
44 data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
45 if (!data) {
46 return SDL_FALSE;
47 }
48 SDL_memcpy(data->DeviceName, deviceName, sizeof(data->DeviceName));
49 data->DeviceMode = devmode;
50 data->DeviceMode.dmFields =
51 (DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY |
52 DM_DISPLAYFLAGS);
53
54 /* Fill in the mode information */
55 mode->format = SDL_PixelFormat_Unknown;
56 mode->w = devmode.dmPelsWidth;
57 mode->h = devmode.dmPelsHeight;
58 mode->refresh_rate = devmode.dmDisplayFrequency;
59 mode->driverdata = data;
60
61 hdc = CreateDC(deviceName, NULL, NULL, &devmode);
62 if (hdc) {
63 char bmi_data[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
64 LPBITMAPINFO bmi;
65 HBITMAP hbm;
66
67 SDL_zero(bmi_data);
68 bmi = (LPBITMAPINFO) bmi_data;
69 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
70
71 hbm = CreateCompatibleBitmap(hdc, 1, 1);
72 GetDIBits(hdc, hbm, 0, 1, NULL, bmi, DIB_RGB_COLORS);
73 GetDIBits(hdc, hbm, 0, 1, NULL, bmi, DIB_RGB_COLORS);
74 DeleteObject(hbm);
75 DeleteDC(hdc);
76 if (bmi->bmiHeader.biCompression == BI_BITFIELDS) {
77 switch (*(Uint32 *) bmi->bmiColors) {
78 case 0x00FF0000:
79 mode->format = SDL_PixelFormat_RGB888;
80 break;
81 case 0x000000FF:
82 mode->format = SDL_PixelFormat_BGR888;
83 break;
84 case 0xF800:
85 mode->format = SDL_PixelFormat_RGB565;
86 break;
87 case 0x7C00:
88 mode->format = SDL_PixelFormat_RGB555;
89 break;
90 }
91 } else if (bmi->bmiHeader.biBitCount == 8) {
92 mode->format = SDL_PixelFormat_Index8;
93 }
94 } else {
95 switch (devmode.dmBitsPerPel) {
96 case 32:
97 mode->format = SDL_PixelFormat_RGB888;
98 break;
99 case 24:
100 mode->format = SDL_PixelFormat_RGB24;
101 break;
102 case 16:
103 mode->format = SDL_PixelFormat_RGB565;
104 break;
105 case 15:
106 mode->format = SDL_PixelFormat_RGB555;
107 break;
108 case 8:
109 mode->format = SDL_PixelFormat_Index8;
110 break;
111 }
112 }
113 return SDL_TRUE;
114 }
115
116 void
117 WIN_InitModes(_THIS)
118 {
119 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
120 DWORD i, j;
121 DISPLAY_DEVICE device;
122
123 device.cb = sizeof(device);
124 for (i = 0;; ++i) {
125 TCHAR DeviceName[32];
126
127 if (!EnumDisplayDevices(NULL, i, &device, 0)) {
128 break;
129 }
130 if (!(device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) {
131 continue;
132 }
133 SDL_memcpy(DeviceName, device.DeviceName, sizeof(DeviceName));
134 #ifdef DEBUG_MODES
135 printf("Device: %s\n", WIN_StringToUTF8(DeviceName));
136 #endif
137 for (j = 0;; ++j) {
138 SDL_VideoDisplay display;
139 SDL_DisplayData *displaydata;
140 SDL_DisplayMode mode;
141
142 if (!EnumDisplayDevices(DeviceName, j, &device, 0)) {
143 break;
144 }
145 if (!(device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) {
146 continue;
147 }
148 #ifdef DEBUG_MODES
149 printf("Monitor: %s\n", WIN_StringToUTF8(device.DeviceName));
150 #endif
151 if (!WIN_GetDisplayMode(DeviceName, ENUM_CURRENT_SETTINGS, &mode)) {
152 break;
153 }
154
155 displaydata =
156 (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata));
157 if (!displaydata) {
158 continue;
159 }
160 SDL_memcpy(displaydata->DeviceName, DeviceName,
161 sizeof(DeviceName));
162
163 SDL_zero(display);
164 display.desktop_mode = mode;
165 display.current_mode = mode;
166 display.driverdata = displaydata;
167 SDL_AddVideoDisplay(&display);
168 }
169 }
170 }
171
172 void
173 WIN_GetDisplayModes(_THIS)
174 {
175 SDL_DisplayData *data = (SDL_DisplayData *) SDL_CurrentDisplay.driverdata;
176 DWORD i;
177 SDL_DisplayMode mode;
178
179 for (i = 0;; ++i) {
180 if (!WIN_GetDisplayMode(data->DeviceName, i, &mode)) {
181 break;
182 }
183 if (!SDL_AddDisplayMode(_this->current_display, &mode)) {
184 SDL_free(mode.driverdata);
185 }
186 }
187 }
188
189 int
190 WIN_SetDisplayMode(_THIS, SDL_DisplayMode * mode)
191 {
192 SDL_DisplayModeData *data = (SDL_DisplayModeData *) mode->driverdata;
193 LONG status;
194
195 status =
196 ChangeDisplaySettingsEx(data->DeviceName, &data->DeviceMode, NULL,
197 CDS_FULLSCREEN, NULL);
198 if (status == DISP_CHANGE_SUCCESSFUL) {
199 return 0;
200 } else {
201 const char *reason = "Unknown reason";
202 switch (status) {
203 case DISP_CHANGE_BADFLAGS:
204 reason = "DISP_CHANGE_BADFLAGS";
205 break;
206 case DISP_CHANGE_BADMODE:
207 reason = "DISP_CHANGE_BADMODE";
208 break;
209 case DISP_CHANGE_BADPARAM:
210 reason = "DISP_CHANGE_BADPARAM";
211 break;
212 case DISP_CHANGE_FAILED:
213 reason = "DISP_CHANGE_FAILED";
214 break;
215 }
216 SDL_SetError("ChangeDisplaySettingsEx() failed: %s", reason);
217 return -1;
218 }
219 }
220
221 void
222 WIN_QuitModes(_THIS)
223 {
224 ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
225 }
226
227 /* vi: set ts=4 sw=4 expandtab: */