SDL-1.2.14
[sdl_omap.git] / src / video / photon / SDL_ph_modes.c
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 }