e14743d1 |
1 | /* |
2 | SDL - Simple DirectMedia Layer |
3 | Copyright (C) 1997-2009 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_ph_modes_c.h" |
25 | |
26 | static PgVideoModeInfo_t mode_info; |
27 | static PgVideoModes_t mode_list; |
28 | |
29 | /* The current list of available video modes */ |
30 | SDL_Rect SDL_modelist[PH_MAX_VIDEOMODES]; |
31 | SDL_Rect* SDL_modearray[PH_MAX_VIDEOMODES]; |
32 | |
33 | static int compare_modes_by_res(const void* mode1, const void* mode2) |
34 | { |
35 | PgVideoModeInfo_t mode1_info; |
36 | PgVideoModeInfo_t mode2_info; |
37 | |
38 | if (PgGetVideoModeInfo(*(unsigned short*)mode1, &mode1_info) < 0) |
39 | { |
40 | return 0; |
41 | } |
42 | |
43 | if (PgGetVideoModeInfo(*(unsigned short*)mode2, &mode2_info) < 0) |
44 | { |
45 | return 0; |
46 | } |
47 | |
48 | if (mode1_info.width == mode2_info.width) |
49 | { |
50 | return mode2_info.height - mode1_info.height; |
51 | } |
52 | else |
53 | { |
54 | return mode2_info.width - mode1_info.width; |
55 | } |
56 | } |
57 | |
58 | SDL_Rect **ph_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) |
59 | { |
60 | int i = 0; |
61 | int j = 0; |
62 | SDL_Rect Amodelist[PH_MAX_VIDEOMODES]; |
63 | |
64 | for (i=0; i<PH_MAX_VIDEOMODES; i++) |
65 | { |
66 | SDL_modearray[i]=&SDL_modelist[i]; |
67 | } |
68 | |
69 | if (PgGetVideoModeList(&mode_list) < 0) |
70 | { |
71 | SDL_SetError("ph_ListModes(): PgGetVideoModeList() function failed !\n"); |
72 | return NULL; |
73 | } |
74 | |
75 | mode_info.bits_per_pixel = 0; |
76 | |
77 | for (i=0; i < mode_list.num_modes; i++) |
78 | { |
79 | if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0) |
80 | { |
81 | SDL_SetError("ph_ListModes(): PgGetVideoModeInfo() function failed on mode: 0x%X.\n", mode_list.modes[i]); |
82 | return NULL; |
83 | } |
84 | if(mode_info.bits_per_pixel == format->BitsPerPixel) |
85 | { |
86 | Amodelist[j].w = mode_info.width; |
87 | Amodelist[j].h = mode_info.height; |
88 | Amodelist[j].x = 0; |
89 | Amodelist[j].y = 0; |
90 | j++; |
91 | } |
92 | } |
93 | |
94 | /* reorder biggest for smallest, assume width dominates */ |
95 | |
96 | for(i=0; i<j; i++) |
97 | { |
98 | SDL_modelist[i].w = Amodelist[j - i - 1].w; |
99 | SDL_modelist[i].h = Amodelist[j - i - 1].h; |
100 | SDL_modelist[i].x = Amodelist[j - i - 1].x; |
101 | SDL_modelist[i].y = Amodelist[j - i - 1].y; |
102 | } |
103 | SDL_modearray[j]=NULL; |
104 | |
105 | return SDL_modearray; |
106 | } |
107 | |
108 | void ph_FreeVideoModes(_THIS) |
109 | { |
110 | return; |
111 | } |
112 | |
113 | /* return the mode associated with width, height and bpp */ |
114 | /* if there is no mode then zero is returned */ |
115 | int ph_GetVideoMode(int width, int height, int bpp) |
116 | { |
117 | int i; |
118 | int modestage=0; |
119 | int closestmode=0; |
120 | |
121 | if (PgGetVideoModeList(&mode_list) < 0) |
122 | { |
123 | return -1; |
124 | } |
125 | |
126 | /* special case for the double-sized 320x200 mode */ |
127 | if ((width==640) && (height==400)) |
128 | { |
129 | modestage=1; |
130 | } |
131 | |
132 | /* search list for exact match */ |
133 | for (i=0; i<mode_list.num_modes; i++) |
134 | { |
135 | if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0) |
136 | { |
137 | return 0; |
138 | } |
139 | |
140 | if ((mode_info.width == width) && (mode_info.height == height) && |
141 | (mode_info.bits_per_pixel == bpp)) |
142 | { |
143 | return mode_list.modes[i]; |
144 | } |
145 | else |
146 | { |
147 | if ((modestage) && (mode_info.width == width) && (mode_info.height == height+80) && |
148 | (mode_info.bits_per_pixel == bpp)) |
149 | { |
150 | modestage=2; |
151 | closestmode=mode_list.modes[i]; |
152 | } |
153 | } |
154 | } |
155 | |
156 | /* if we are here, then no 640x400xbpp mode found and we'll emulate it via 640x480xbpp mode */ |
157 | if (modestage==2) |
158 | { |
159 | return closestmode; |
160 | } |
161 | |
162 | return (i == mode_list.num_modes) ? 0 : mode_list.modes[i]; |
163 | } |
164 | |
165 | /* return the mode associated with width, height and bpp */ |
166 | /* if requested bpp is not found the mode with closest bpp is returned */ |
167 | int get_mode_any_format(int width, int height, int bpp) |
168 | { |
169 | int i, closest, delta, min_delta; |
170 | |
171 | if (PgGetVideoModeList(&mode_list) < 0) |
172 | { |
173 | return -1; |
174 | } |
175 | |
176 | SDL_qsort(mode_list.modes, mode_list.num_modes, sizeof(unsigned short), compare_modes_by_res); |
177 | |
178 | for(i=0;i<mode_list.num_modes;i++) |
179 | { |
180 | if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0) |
181 | { |
182 | return 0; |
183 | } |
184 | if ((mode_info.width == width) && (mode_info.height == height)) |
185 | { |
186 | break; |
187 | } |
188 | } |
189 | |
190 | if (i<mode_list.num_modes) |
191 | { |
192 | /* get closest bpp */ |
193 | closest = i++; |
194 | if (mode_info.bits_per_pixel == bpp) |
195 | { |
196 | return mode_list.modes[closest]; |
197 | } |
198 | |
199 | min_delta = abs(mode_info.bits_per_pixel - bpp); |
200 | |
201 | while(1) |
202 | { |
203 | if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0) |
204 | { |
205 | return 0; |
206 | } |
207 | |
208 | if ((mode_info.width != width) || (mode_info.height != height)) |
209 | { |
210 | break; |
211 | } |
212 | else |
213 | { |
214 | if (mode_info.bits_per_pixel == bpp) |
215 | { |
216 | closest = i; |
217 | break; |
218 | } |
219 | else |
220 | { |
221 | delta = abs(mode_info.bits_per_pixel - bpp); |
222 | if (delta < min_delta) |
223 | { |
224 | closest = i; |
225 | min_delta = delta; |
226 | } |
227 | i++; |
228 | } |
229 | } |
230 | } |
231 | return mode_list.modes[closest]; |
232 | } |
233 | |
234 | return 0; |
235 | } |
236 | |
237 | int ph_ToggleFullScreen(_THIS, int on) |
238 | { |
239 | return -1; |
240 | } |
241 | |
242 | int ph_EnterFullScreen(_THIS, SDL_Surface* screen, int fmode) |
243 | { |
244 | PgDisplaySettings_t settings; |
245 | int mode; |
246 | char* refreshrate; |
247 | int refreshratenum; |
248 | |
249 | if (!currently_fullscreen) |
250 | { |
251 | /* Get the video mode and set it */ |
252 | if (screen->flags & SDL_ANYFORMAT) |
253 | { |
254 | if ((mode = get_mode_any_format(screen->w, screen->h, screen->format->BitsPerPixel)) == 0) |
255 | { |
256 | SDL_SetError("ph_EnterFullScreen(): can't find appropriate video mode !\n"); |
257 | return 0; |
258 | } |
259 | } |
260 | else |
261 | { |
262 | if ((mode = ph_GetVideoMode(screen->w, screen->h, screen->format->BitsPerPixel)) == 0) |
263 | { |
264 | SDL_SetError("ph_EnterFullScreen(): can't find appropriate video mode !\n"); |
265 | return 0; |
266 | } |
267 | if (PgGetVideoModeInfo(mode, &mode_info) < 0) |
268 | { |
269 | SDL_SetError("ph_EnterFullScreen(): can't get video mode capabilities !\n"); |
270 | return 0; |
271 | } |
272 | if (mode_info.height != screen->h) |
273 | { |
274 | if ((mode_info.height==480) && (screen->h==400)) |
275 | { |
276 | videomode_emulatemode=1; |
277 | } |
278 | } |
279 | else |
280 | { |
281 | videomode_emulatemode=0; |
282 | } |
283 | } |
284 | |
285 | /* save old video mode caps */ |
286 | PgGetVideoMode(&settings); |
287 | old_video_mode=settings.mode; |
288 | old_refresh_rate=settings.refresh; |
289 | |
290 | /* setup new video mode */ |
291 | settings.mode = mode; |
292 | settings.refresh = 0; |
293 | settings.flags = 0; |
294 | |
295 | refreshrate=SDL_getenv("SDL_PHOTON_FULLSCREEN_REFRESH"); |
296 | if (refreshrate!=NULL) |
297 | { |
298 | if (SDL_sscanf(refreshrate, "%d", &refreshratenum)==1) |
299 | { |
300 | settings.refresh = refreshratenum; |
301 | } |
302 | } |
303 | |
304 | if (PgSetVideoMode(&settings) < 0) |
305 | { |
306 | SDL_SetError("ph_EnterFullScreen(): PgSetVideoMode() call failed !\n"); |
307 | return 0; |
308 | } |
309 | |
310 | if (this->screen) |
311 | { |
312 | if ((this->screen->flags & SDL_OPENGL)==SDL_OPENGL) |
313 | { |
314 | #if !SDL_VIDEO_OPENGL || (_NTO_VERSION < 630) |
315 | return 0; /* 6.3.0 */ |
316 | #endif |
317 | } |
318 | } |
319 | |
320 | if (fmode==0) |
321 | { |
322 | if (OCImage.direct_context==NULL) |
323 | { |
324 | OCImage.direct_context=(PdDirectContext_t*)PdCreateDirectContext(); |
325 | if (!OCImage.direct_context) |
326 | { |
327 | SDL_SetError("ph_EnterFullScreen(): Can't create direct context !\n"); |
328 | ph_LeaveFullScreen(this); |
329 | return 0; |
330 | } |
331 | } |
332 | OCImage.oldDC=PdDirectStart(OCImage.direct_context); |
333 | } |
334 | |
335 | currently_fullscreen = 1; |
336 | } |
337 | PgFlush(); |
338 | |
339 | return 1; |
340 | } |
341 | |
342 | int ph_LeaveFullScreen(_THIS) |
343 | { |
344 | PgDisplaySettings_t oldmode_settings; |
345 | |
346 | if (currently_fullscreen) |
347 | { |
348 | if ((this->screen) && ((this->screen->flags & SDL_OPENGL)==SDL_OPENGL)) |
349 | { |
350 | #if !SDL_VIDEO_OPENGL || (_NTO_VERSION < 630) |
351 | return 0; |
352 | #endif |
353 | } |
354 | |
355 | /* release routines starts here */ |
356 | { |
357 | if (OCImage.direct_context) |
358 | { |
359 | PdDirectStop(OCImage.direct_context); |
360 | PdReleaseDirectContext(OCImage.direct_context); |
361 | OCImage.direct_context=NULL; |
362 | } |
363 | if (OCImage.oldDC) |
364 | { |
365 | PhDCSetCurrent(OCImage.oldDC); |
366 | OCImage.oldDC=NULL; |
367 | } |
368 | |
369 | currently_fullscreen=0; |
370 | |
371 | /* Restore old video mode */ |
372 | if (old_video_mode != -1) |
373 | { |
374 | oldmode_settings.mode = (unsigned short) old_video_mode; |
375 | oldmode_settings.refresh = (unsigned short) old_refresh_rate; |
376 | oldmode_settings.flags = 0; |
377 | |
378 | if (PgSetVideoMode(&oldmode_settings) < 0) |
379 | { |
380 | SDL_SetError("Ph_LeaveFullScreen(): PgSetVideoMode() function failed !\n"); |
381 | return 0; |
382 | } |
383 | } |
384 | |
385 | old_video_mode=-1; |
386 | old_refresh_rate=-1; |
387 | } |
388 | } |
389 | return 1; |
390 | } |