src/video/photon/SDL_ph_modes.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 12 Nov 2004 21:25:42 +0000
changeset 966 f72cc0c7305f
parent 910 4ab6d1fd028f
child 1289 c07c6ef7c93e
permissions -rw-r--r--
Video modes are sorted width first, then height
slouken@0
     1
/*
slouken@0
     2
    SDL - Simple DirectMedia Layer
slouken@769
     3
    Copyright (C) 1997-2004 Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@0
     6
    modify it under the terms of the GNU Library General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@0
     8
    version 2 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@0
    13
    Library General Public License for more details.
slouken@0
    14
slouken@0
    15
    You should have received a copy of the GNU Library General Public
slouken@0
    16
    License along with this library; if not, write to the Free
slouken@0
    17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@0
    21
*/
slouken@0
    22
slouken@0
    23
#ifdef SAVE_RCSID
slouken@0
    24
static char rcsid =
slouken@0
    25
 "@(#) $Id$";
slouken@0
    26
#endif
slouken@0
    27
slouken@663
    28
#include "SDL_error.h"
slouken@0
    29
#include "SDL_ph_modes_c.h"
slouken@0
    30
slouken@0
    31
static unsigned long key1, key2;
slouken@0
    32
static PgVideoModeInfo_t mode_info;
slouken@0
    33
static PgVideoModes_t mode_list;
slouken@266
    34
slouken@571
    35
/* The current list of available video modes */
slouken@266
    36
SDL_Rect  SDL_modelist[PH_MAX_VIDEOMODES];
slouken@266
    37
SDL_Rect* SDL_modearray[PH_MAX_VIDEOMODES];
slouken@0
    38
slouken@0
    39
static int compare_modes_by_res(const void* mode1, const void* mode2)
slouken@0
    40
{
slouken@966
    41
    PgVideoModeInfo_t mode1_info;
slouken@966
    42
    PgVideoModeInfo_t mode2_info;
slouken@966
    43
slouken@966
    44
    if (PgGetVideoModeInfo(*(unsigned short*)mode1, &mode1_info) < 0)
slouken@571
    45
    {
slouken@571
    46
        return 0;
slouken@571
    47
    }
slouken@0
    48
slouken@966
    49
    if (PgGetVideoModeInfo(*(unsigned short*)mode2, &mode2_info) < 0)
slouken@571
    50
    {
slouken@571
    51
        return 0;
slouken@571
    52
    }
slouken@0
    53
slouken@966
    54
    if (mode1_info.width == mode2_info.width)
slouken@663
    55
    {
slouken@966
    56
        return mode2_info.height - mode1_info.height;
slouken@663
    57
    }
slouken@571
    58
    else
slouken@663
    59
    {
slouken@966
    60
        return mode2_info.width - mode1_info.width;
slouken@663
    61
    }
slouken@0
    62
}
slouken@0
    63
slouken@266
    64
SDL_Rect **ph_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
slouken@0
    65
{
slouken@309
    66
    int i = 0;
slouken@309
    67
    int j = 0;
slouken@309
    68
    SDL_Rect Amodelist[PH_MAX_VIDEOMODES];
slouken@0
    69
slouken@309
    70
    for (i=0; i<PH_MAX_VIDEOMODES; i++)
slouken@309
    71
    {
slouken@309
    72
        SDL_modearray[i]=&SDL_modelist[i];
slouken@309
    73
    }
slouken@309
    74
slouken@821
    75
    if (PgGetVideoModeList(&mode_list) < 0)
slouken@309
    76
    {
slouken@663
    77
       SDL_SetError("ph_ListModes(): PgGetVideoModeList() function failed !\n");
slouken@309
    78
       return NULL;
slouken@309
    79
    }
slouken@309
    80
slouken@309
    81
    mode_info.bits_per_pixel = 0;
slouken@309
    82
slouken@309
    83
    for (i=0; i < mode_list.num_modes; i++) 
slouken@309
    84
    {
slouken@309
    85
        if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0)
slouken@266
    86
        {
slouken@663
    87
            SDL_SetError("ph_ListModes(): PgGetVideoModeInfo() function failed on mode: 0x%X.\n", mode_list.modes[i]);
slouken@309
    88
            return NULL;
slouken@266
    89
        }
slouken@309
    90
        if(mode_info.bits_per_pixel == format->BitsPerPixel)
slouken@309
    91
        {
slouken@309
    92
            Amodelist[j].w = mode_info.width;
slouken@309
    93
            Amodelist[j].h = mode_info.height;
slouken@309
    94
            Amodelist[j].x = 0;
slouken@309
    95
            Amodelist[j].y = 0;
slouken@309
    96
            j++;	
slouken@309
    97
        }
slouken@309
    98
    }
slouken@309
    99
	
slouken@309
   100
    /* reorder biggest for smallest, assume width dominates */
slouken@0
   101
slouken@309
   102
    for(i=0; i<j; i++)
slouken@309
   103
    {
slouken@821
   104
        SDL_modelist[i].w = Amodelist[j - i - 1].w;
slouken@821
   105
        SDL_modelist[i].h = Amodelist[j - i - 1].h;
slouken@821
   106
        SDL_modelist[i].x = Amodelist[j - i - 1].x;
slouken@821
   107
        SDL_modelist[i].y = Amodelist[j - i - 1].y;
slouken@309
   108
    }
slouken@309
   109
    SDL_modearray[j]=NULL;
slouken@0
   110
	
slouken@309
   111
    return SDL_modearray;
slouken@0
   112
}
slouken@0
   113
slouken@0
   114
void ph_FreeVideoModes(_THIS)
slouken@0
   115
{
slouken@266
   116
   return;
slouken@0
   117
}
slouken@0
   118
slouken@309
   119
/* return the mode associated with width, height and bpp */
slouken@309
   120
/* if there is no mode then zero is returned             */
slouken@663
   121
int ph_GetVideoMode(int width, int height, int bpp)
slouken@0
   122
{
slouken@309
   123
    int i;
slouken@821
   124
    int modestage=0;
slouken@821
   125
    int closestmode=0;
slouken@0
   126
slouken@309
   127
    if (PgGetVideoModeList(&mode_list) < 0)
slouken@309
   128
    {
slouken@309
   129
        return -1;
slouken@309
   130
    }
slouken@0
   131
slouken@821
   132
    /* special case for the double-sized 320x200 mode */
slouken@821
   133
    if ((width==640) && (height==400))
slouken@821
   134
    {
slouken@821
   135
       modestage=1;
slouken@821
   136
    }
slouken@821
   137
slouken@309
   138
    /* search list for exact match */
slouken@821
   139
    for (i=0; i<mode_list.num_modes; i++)
slouken@309
   140
    {
slouken@309
   141
        if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0)
slouken@309
   142
        {
slouken@309
   143
            return 0;
slouken@309
   144
        }
slouken@0
   145
slouken@821
   146
        if ((mode_info.width == width) && (mode_info.height == height) && 
slouken@309
   147
            (mode_info.bits_per_pixel == bpp))
slouken@309
   148
        {
slouken@309
   149
            return mode_list.modes[i];
slouken@309
   150
        }
slouken@821
   151
        else
slouken@821
   152
        {
slouken@821
   153
           if ((modestage) && (mode_info.width == width) && (mode_info.height == height+80) && 
slouken@821
   154
               (mode_info.bits_per_pixel == bpp))
slouken@821
   155
           {
slouken@821
   156
              modestage=2;
slouken@821
   157
              closestmode=mode_list.modes[i];
slouken@821
   158
           }
slouken@821
   159
        }
slouken@821
   160
    }
slouken@821
   161
slouken@821
   162
    /* if we are here, then no 640x400xbpp mode found and we'll emulate it via 640x480xbpp mode */
slouken@821
   163
    if (modestage==2)
slouken@821
   164
    {
slouken@821
   165
       return closestmode;
slouken@309
   166
    }
slouken@0
   167
slouken@309
   168
    return (i == mode_list.num_modes) ? 0 : mode_list.modes[i];
slouken@0
   169
}
slouken@0
   170
slouken@821
   171
/* return the mode associated with width, height and bpp               */
slouken@0
   172
/* if requested bpp is not found the mode with closest bpp is returned */
slouken@663
   173
int get_mode_any_format(int width, int height, int bpp)
slouken@0
   174
{
slouken@0
   175
    int i, closest, delta, min_delta;
slouken@0
   176
slouken@663
   177
    if (PgGetVideoModeList(&mode_list) < 0)
slouken@663
   178
    {
slouken@663
   179
        return -1;
slouken@663
   180
    }
slouken@0
   181
slouken@663
   182
    qsort(mode_list.modes, mode_list.num_modes, sizeof(unsigned short), compare_modes_by_res);
slouken@663
   183
slouken@663
   184
    for(i=0;i<mode_list.num_modes;i++)
slouken@663
   185
    {
slouken@663
   186
        if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0)
slouken@663
   187
        {
slouken@663
   188
            return 0;
slouken@663
   189
        }
slouken@663
   190
        if ((mode_info.width == width) && (mode_info.height == height))
slouken@663
   191
        {
slouken@0
   192
           break;
slouken@663
   193
        }
slouken@663
   194
    }
slouken@0
   195
slouken@663
   196
    if (i<mode_list.num_modes)
slouken@663
   197
    {
slouken@663
   198
        /* get closest bpp */
slouken@663
   199
        closest = i++;
slouken@663
   200
        if (mode_info.bits_per_pixel == bpp)
slouken@663
   201
        {
slouken@663
   202
            return mode_list.modes[closest];
slouken@663
   203
        }
slouken@0
   204
slouken@663
   205
        min_delta = abs(mode_info.bits_per_pixel - bpp);
slouken@663
   206
slouken@663
   207
        while(1)
slouken@663
   208
        {
slouken@663
   209
            if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0)
slouken@663
   210
            {
slouken@663
   211
                return 0;
slouken@663
   212
            }
slouken@663
   213
slouken@663
   214
            if ((mode_info.width != width) || (mode_info.height != height))
slouken@663
   215
            {
slouken@663
   216
                break;
slouken@663
   217
            }
slouken@663
   218
            else
slouken@663
   219
            {
slouken@663
   220
                if (mode_info.bits_per_pixel == bpp)
slouken@663
   221
                {
slouken@663
   222
                    closest = i;
slouken@663
   223
                    break;
slouken@663
   224
                }
slouken@663
   225
                else
slouken@663
   226
                {
slouken@663
   227
                    delta = abs(mode_info.bits_per_pixel - bpp);
slouken@663
   228
                    if (delta < min_delta)
slouken@663
   229
                    {
slouken@663
   230
                        closest = i;
slouken@663
   231
                        min_delta = delta;
slouken@663
   232
                    }
slouken@663
   233
                    i++;
slouken@663
   234
                }
slouken@663
   235
            }
slouken@663
   236
        }
slouken@663
   237
        return mode_list.modes[closest];
slouken@663
   238
    }
slouken@663
   239
slouken@309
   240
    return 0;
slouken@0
   241
}
slouken@0
   242
slouken@0
   243
int ph_ToggleFullScreen(_THIS, int on)
slouken@0
   244
{
slouken@663
   245
    return -1;
slouken@0
   246
}
slouken@0
   247
slouken@910
   248
int ph_EnterFullScreen(_THIS, SDL_Surface* screen, int fmode)
slouken@0
   249
{
slouken@663
   250
    PgDisplaySettings_t settings;
slouken@663
   251
    int mode;
slouken@821
   252
    char* refreshrate;
slouken@821
   253
    int refreshratenum;
slouken@663
   254
slouken@309
   255
    if (!currently_fullscreen)
slouken@309
   256
    {
slouken@663
   257
        /* Get the video mode and set it */
slouken@663
   258
        if (screen->flags & SDL_ANYFORMAT)
slouken@663
   259
        {
slouken@663
   260
            if ((mode = get_mode_any_format(screen->w, screen->h, screen->format->BitsPerPixel)) == 0)
slouken@663
   261
            {
slouken@663
   262
                SDL_SetError("ph_EnterFullScreen(): can't find appropriate video mode !\n");
slouken@663
   263
                return 0;
slouken@663
   264
            }
slouken@663
   265
        }
slouken@663
   266
        else
slouken@663
   267
        {
slouken@663
   268
            if ((mode = ph_GetVideoMode(screen->w, screen->h, screen->format->BitsPerPixel)) == 0)
slouken@663
   269
            {
slouken@663
   270
                SDL_SetError("ph_EnterFullScreen(): can't find appropriate video mode !\n");
slouken@663
   271
                return 0;
slouken@663
   272
            }
slouken@821
   273
            if (PgGetVideoModeInfo(mode, &mode_info) < 0)
slouken@821
   274
            {
slouken@821
   275
                SDL_SetError("ph_EnterFullScreen(): can't get video mode capabilities !\n");
slouken@821
   276
                return 0;
slouken@821
   277
            }
slouken@821
   278
            if (mode_info.height != screen->h)
slouken@821
   279
            {
slouken@821
   280
               if ((mode_info.height==480) && (screen->h==400))
slouken@821
   281
               {
slouken@821
   282
                  videomode_emulatemode=1;
slouken@821
   283
               }
slouken@821
   284
            }
slouken@821
   285
            else
slouken@821
   286
            {
slouken@821
   287
               videomode_emulatemode=0;
slouken@821
   288
            }
slouken@663
   289
        }
slouken@663
   290
slouken@663
   291
        /* save old video mode caps */
slouken@663
   292
        PgGetVideoMode(&settings);
slouken@663
   293
        old_video_mode=settings.mode;
slouken@663
   294
        old_refresh_rate=settings.refresh;
slouken@663
   295
slouken@663
   296
        /* setup new video mode */
slouken@663
   297
        settings.mode = mode;
slouken@663
   298
        settings.refresh = 0;
slouken@663
   299
        settings.flags = 0;
slouken@663
   300
slouken@821
   301
        refreshrate=getenv("SDL_PHOTON_FULLSCREEN_REFRESH");
slouken@821
   302
        if (refreshrate!=NULL)
slouken@821
   303
        {
slouken@821
   304
           if (sscanf(refreshrate, "%d", &refreshratenum)==1)
slouken@821
   305
           {
slouken@821
   306
               settings.refresh = refreshratenum;
slouken@821
   307
           }
slouken@821
   308
        }
slouken@821
   309
slouken@663
   310
        if (PgSetVideoMode(&settings) < 0)
slouken@663
   311
        {
slouken@663
   312
            SDL_SetError("ph_EnterFullScreen(): PgSetVideoMode() call failed !\n");
slouken@663
   313
            return 0;
slouken@663
   314
        }
slouken@663
   315
slouken@315
   316
        if (this->screen)
slouken@309
   317
        {
slouken@315
   318
            if ((this->screen->flags & SDL_OPENGL)==SDL_OPENGL)
slouken@315
   319
            {
slouken@309
   320
#ifdef HAVE_OPENGL
slouken@910
   321
    #if (_NTO_VERSION < 630)
slouken@910
   322
                return 0;
slouken@910
   323
    #endif /* 6.3.0 */
slouken@910
   324
#else
slouken@910
   325
                return 0;
slouken@309
   326
#endif /* HAVE_OPENGL */
slouken@315
   327
            }
slouken@309
   328
        }
slouken@315
   329
slouken@910
   330
        if (fmode==0)
slouken@309
   331
        {
slouken@910
   332
            if (OCImage.direct_context==NULL)
slouken@663
   333
            {
slouken@910
   334
                OCImage.direct_context=(PdDirectContext_t*)PdCreateDirectContext();
slouken@910
   335
                if (!OCImage.direct_context)
slouken@910
   336
                {
slouken@910
   337
                    SDL_SetError("ph_EnterFullScreen(): Can't create direct context !\n");
slouken@910
   338
                    ph_LeaveFullScreen(this);
slouken@910
   339
                    return 0;
slouken@910
   340
                }
slouken@663
   341
            }
slouken@910
   342
            OCImage.oldDC=PdDirectStart(OCImage.direct_context);
slouken@315
   343
        }
slouken@0
   344
slouken@315
   345
        currently_fullscreen = 1;
slouken@309
   346
    }
slouken@692
   347
    PgFlush();
slouken@0
   348
slouken@309
   349
    return 1;
slouken@0
   350
}
slouken@0
   351
slouken@315
   352
int ph_LeaveFullScreen(_THIS)
slouken@0
   353
{
slouken@692
   354
    PgDisplaySettings_t oldmode_settings;
slouken@0
   355
       
slouken@309
   356
    if (currently_fullscreen)
slouken@309
   357
    {
slouken@663
   358
        if ((this->screen) && ((this->screen->flags & SDL_OPENGL)==SDL_OPENGL))
slouken@309
   359
        {
slouken@309
   360
#ifdef HAVE_OPENGL
slouken@910
   361
    #if (_NTO_VERSION < 630)
slouken@910
   362
            return 0;
slouken@910
   363
    #endif /* 6.3.0 */
slouken@910
   364
#else
slouken@910
   365
            return 0;
slouken@309
   366
#endif /* HAVE_OPENGL */
slouken@309
   367
        }
slouken@910
   368
slouken@910
   369
        /* release routines starts here */
slouken@309
   370
        {
slouken@663
   371
            if (OCImage.direct_context)
slouken@663
   372
            {
slouken@663
   373
                PdDirectStop(OCImage.direct_context);
slouken@663
   374
                PdReleaseDirectContext(OCImage.direct_context);
slouken@663
   375
                OCImage.direct_context=NULL;
slouken@663
   376
            }
slouken@663
   377
            if (OCImage.oldDC)
slouken@663
   378
            {
slouken@663
   379
                PhDCSetCurrent(OCImage.oldDC);
slouken@663
   380
                OCImage.oldDC=NULL;
slouken@663
   381
            }
slouken@571
   382
slouken@315
   383
            currently_fullscreen=0;
slouken@0
   384
slouken@309
   385
            /* Restore old video mode */
slouken@309
   386
            if (old_video_mode != -1)
slouken@309
   387
            {
slouken@692
   388
                oldmode_settings.mode = (unsigned short) old_video_mode;
slouken@692
   389
                oldmode_settings.refresh = (unsigned short) old_refresh_rate;
slouken@692
   390
                oldmode_settings.flags = 0;
slouken@315
   391
                
slouken@692
   392
                if (PgSetVideoMode(&oldmode_settings) < 0)
slouken@309
   393
                {
slouken@663
   394
                    SDL_SetError("Ph_LeaveFullScreen(): PgSetVideoMode() function failed !\n");
slouken@571
   395
                    return 0;
slouken@309
   396
                }
slouken@309
   397
            }
slouken@309
   398
slouken@309
   399
            old_video_mode=-1;
slouken@315
   400
            old_refresh_rate=-1;
slouken@309
   401
        }
slouken@309
   402
    }
slouken@309
   403
    return 1;
slouken@0
   404
}