Home | History | Annotate | Download | only in photon
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2012 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 (at) 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 }
    391