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