src/video/photon/SDL_ph_modes.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 28 May 2006 13:04:16 +0000
branchSDL-1.3
changeset 1662 782fd950bd46
parent 1658 e49147870aac
child 1668 4da1ee79c9af
permissions -rw-r--r--
Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API.

WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid.

The code is now run through a consistent indent format:
indent -i4 -nut -nsc -br -ce

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