Mercurial > sdl-ios-xcode
comparison src/video/cocoa/SDL_cocoamodes.m @ 1934:70139af5ac27
Implemented Mac OS X video mode selection.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 24 Jul 2006 07:21:16 +0000 |
parents | 103c6fec2a60 |
children | 5d3724f64f2b |
comparison
equal
deleted
inserted
replaced
1933:7ee5297340f7 | 1934:70139af5ac27 |
---|---|
21 */ | 21 */ |
22 #include "SDL_config.h" | 22 #include "SDL_config.h" |
23 | 23 |
24 #include "SDL_cocoavideo.h" | 24 #include "SDL_cocoavideo.h" |
25 | 25 |
26 static void | |
27 CG_SetError(const char *prefix, CGDisplayErr result) | |
28 { | |
29 const char *error; | |
30 | |
31 switch (result) { | |
32 case kCGErrorFailure: | |
33 error = "kCGErrorFailure"; | |
34 break; | |
35 case kCGErrorIllegalArgument: | |
36 error = "kCGErrorIllegalArgument"; | |
37 break; | |
38 case kCGErrorInvalidConnection: | |
39 error = "kCGErrorInvalidConnection"; | |
40 break; | |
41 case kCGErrorInvalidContext: | |
42 error = "kCGErrorInvalidContext"; | |
43 break; | |
44 case kCGErrorCannotComplete: | |
45 error = "kCGErrorCannotComplete"; | |
46 break; | |
47 case kCGErrorNameTooLong: | |
48 error = "kCGErrorNameTooLong"; | |
49 break; | |
50 case kCGErrorNotImplemented: | |
51 error = "kCGErrorNotImplemented"; | |
52 break; | |
53 case kCGErrorRangeCheck: | |
54 error = "kCGErrorRangeCheck"; | |
55 break; | |
56 case kCGErrorTypeCheck: | |
57 error = "kCGErrorTypeCheck"; | |
58 break; | |
59 case kCGErrorNoCurrentPoint: | |
60 error = "kCGErrorNoCurrentPoint"; | |
61 break; | |
62 case kCGErrorInvalidOperation: | |
63 error = "kCGErrorInvalidOperation"; | |
64 break; | |
65 case kCGErrorNoneAvailable: | |
66 error = "kCGErrorNoneAvailable"; | |
67 break; | |
68 default: | |
69 error = "Unknown Error"; | |
70 break; | |
71 } | |
72 SDL_SetError("%s: %s", prefix, error); | |
73 } | |
74 | |
75 static SDL_bool | |
76 GetDisplayMode(CFDictionaryRef moderef, SDL_DisplayMode *mode) | |
77 { | |
78 SDL_DisplayModeData *data; | |
79 CFNumberRef number; | |
80 long width, height, bpp, refreshRate; | |
81 | |
82 data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data)); | |
83 if (!data) { | |
84 return SDL_FALSE; | |
85 } | |
86 data->moderef = moderef; | |
87 | |
88 number = CFDictionaryGetValue(moderef, kCGDisplayWidth); | |
89 CFNumberGetValue(number, kCFNumberLongType, &width); | |
90 number = CFDictionaryGetValue(moderef, kCGDisplayHeight); | |
91 CFNumberGetValue(number, kCFNumberLongType, &height); | |
92 number = CFDictionaryGetValue(moderef, kCGDisplayBitsPerPixel); | |
93 CFNumberGetValue(number, kCFNumberLongType, &bpp); | |
94 number = CFDictionaryGetValue(moderef, kCGDisplayRefreshRate); | |
95 CFNumberGetValue(number, kCFNumberLongType, &refreshRate); | |
96 | |
97 mode->format = SDL_PixelFormat_Unknown; | |
98 switch (bpp) { | |
99 case 8: | |
100 mode->format = SDL_PixelFormat_Index8; | |
101 break; | |
102 case 16: | |
103 mode->format = SDL_PixelFormat_RGB555; | |
104 break; | |
105 case 32: | |
106 mode->format = SDL_PixelFormat_RGB888; | |
107 break; | |
108 } | |
109 mode->w = width; | |
110 mode->h = height; | |
111 mode->refresh_rate = refreshRate; | |
112 mode->driverdata = data; | |
113 return SDL_TRUE; | |
114 } | |
26 | 115 |
27 void | 116 void |
28 Cocoa_InitModes(_THIS) | 117 Cocoa_InitModes(_THIS) |
29 { | 118 { |
30 SDL_VideoDisplay display; | 119 CGDisplayErr result; |
120 CGDirectDisplayID *displays; | |
121 CGDisplayCount numDisplays; | |
122 int i; | |
123 | |
124 result = CGGetOnlineDisplayList(0, NULL, &numDisplays); | |
125 if (result != kCGErrorSuccess) { | |
126 CG_SetError("CGGetOnlineDisplayList()", result); | |
127 return; | |
128 } | |
129 displays = SDL_stack_alloc(CGDirectDisplayID, numDisplays); | |
130 result = CGGetOnlineDisplayList(numDisplays, displays, &numDisplays); | |
131 if (result != kCGErrorSuccess) { | |
132 CG_SetError("CGGetOnlineDisplayList()", result); | |
133 SDL_stack_free(displays); | |
134 return; | |
135 } | |
136 | |
137 for (i = 0; i < numDisplays; ++i) { | |
138 SDL_VideoDisplay display; | |
139 SDL_DisplayData *displaydata; | |
140 SDL_DisplayMode mode; | |
141 CFDictionaryRef moderef; | |
142 | |
143 if (CGDisplayIsInMirrorSet(displays[i])) { | |
144 continue; | |
145 } | |
146 moderef = CGDisplayCurrentMode(displays[i]); | |
147 if (!moderef) { | |
148 continue; | |
149 } | |
150 | |
151 displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata)); | |
152 if (!displaydata) { | |
153 continue; | |
154 } | |
155 displaydata->display = displays[i]; | |
156 | |
157 SDL_zero(display); | |
158 if (!GetDisplayMode (moderef, &mode)) { | |
159 SDL_free(displaydata); | |
160 continue; | |
161 } | |
162 display.desktop_mode = mode; | |
163 display.current_mode = mode; | |
164 display.driverdata = displaydata; | |
165 SDL_AddVideoDisplay(&display); | |
166 } | |
167 } | |
168 | |
169 static void | |
170 AddDisplayMode(const void *moderef, void *context) | |
171 { | |
172 SDL_VideoDevice *_this = (SDL_VideoDevice *) context; | |
31 SDL_DisplayMode mode; | 173 SDL_DisplayMode mode; |
32 | 174 |
33 SDL_zero(display); | 175 if (GetDisplayMode(moderef, &mode)) { |
34 SDL_zero(mode); | 176 SDL_AddDisplayMode(_this->current_display, &mode); |
35 display.desktop_mode = mode; | 177 } |
36 display.current_mode = mode; | |
37 SDL_AddVideoDisplay(&display); | |
38 } | 178 } |
39 | 179 |
40 void | 180 void |
41 Cocoa_GetDisplayModes(_THIS) | 181 Cocoa_GetDisplayModes(_THIS) |
42 { | 182 { |
183 SDL_DisplayData *data = (SDL_DisplayData *) SDL_CurrentDisplay.driverdata; | |
184 CFArrayRef modes; | |
185 CFRange range; | |
186 | |
187 modes = CGDisplayAvailableModes(data->display); | |
188 if (!modes) { | |
189 return; | |
190 } | |
191 range.location = 0; | |
192 range.length = CFArrayGetCount(modes); | |
193 CFArrayApplyFunction(modes, range, AddDisplayMode, _this); | |
43 } | 194 } |
44 | 195 |
45 int | 196 int |
46 Cocoa_SetDisplayMode(_THIS, SDL_DisplayMode * mode) | 197 Cocoa_SetDisplayMode(_THIS, SDL_DisplayMode * mode) |
47 { | 198 { |
199 SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_CurrentDisplay.driverdata; | |
200 SDL_DisplayModeData *data = (SDL_DisplayModeData *) mode->driverdata; | |
201 CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken; | |
202 CGError result; | |
203 | |
204 /* Fade to black to hide resolution-switching flicker */ | |
205 if (CGAcquireDisplayFadeReservation(5, &fade_token) == kCGErrorSuccess) { | |
206 CGDisplayFade(fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE); | |
207 } | |
208 | |
209 /* Put up the blanking window (a window above all other windows) */ | |
210 result = CGDisplayCapture(displaydata->display); | |
211 if (result != kCGErrorSuccess) { | |
212 CG_SetError("CGDisplayCapture()", result); | |
213 goto ERR_NO_CAPTURE; | |
214 } | |
215 | |
216 /* Do the physical switch */ | |
217 result = CGDisplaySwitchToMode(displaydata->display, data->moderef); | |
218 if (result != kCGErrorSuccess) { | |
219 CG_SetError("CGDisplaySwitchToMode()", result); | |
220 goto ERR_NO_SWITCH; | |
221 } | |
222 | |
223 /* Fade in again (asynchronously) */ | |
224 if (fade_token != kCGDisplayFadeReservationInvalidToken) { | |
225 CGDisplayFade(fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); | |
226 CGReleaseDisplayFadeReservation(fade_token); | |
227 } | |
228 return 0; | |
229 | |
230 /* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */ | |
231 ERR_NO_SWITCH: | |
232 CGDisplayRelease(displaydata->display); | |
233 ERR_NO_CAPTURE: | |
234 if (fade_token != kCGDisplayFadeReservationInvalidToken) { | |
235 CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); | |
236 CGReleaseDisplayFadeReservation(fade_token); | |
237 } | |
48 return -1; | 238 return -1; |
49 } | 239 } |
50 | 240 |
51 void | 241 void |
52 Cocoa_QuitModes(_THIS) | 242 Cocoa_QuitModes(_THIS) |
53 { | 243 { |
244 int i, saved_display; | |
245 | |
246 saved_display = _this->current_display; | |
247 for (i = 0; i < _this->num_displays; ++i) { | |
248 SDL_VideoDisplay *display = &_this->displays[i]; | |
249 | |
250 if (display->current_mode.driverdata != display->desktop_mode.driverdata) { | |
251 _this->current_display = i; | |
252 Cocoa_SetDisplayMode(_this, &display->desktop_mode); | |
253 } | |
254 } | |
255 CGReleaseAllDisplays(); | |
256 _this->current_display = saved_display; | |
54 } | 257 } |
55 | 258 |
56 /* vi: set ts=4 sw=4 expandtab: */ | 259 /* vi: set ts=4 sw=4 expandtab: */ |