src/video/photon/SDL_ph_modes.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 14 Feb 2004 20:22:21 +0000
changeset 821 30168104389f
parent 769 b8d311d90021
child 910 4ab6d1fd028f
permissions -rw-r--r--
Date: Sat, 14 Feb 2004 14:52:40 +0200
From: "Mike Gorchak"
Subject: Batch of the QNX6 fixes for the SDL

1. Updated readme.QNX
2. Fixed crashes during intensive window updating under fast machines (got over 200 rectangles for update).
3. Fixed double-buffered fullscreen modes, now it works as needed.
4. Fixed Photon detection algorithm.
5. Fixed HWSURFACE update function.
6. Added SDL_PHOTON_FULLSCREEN_REFRESH environment variable support for control refresh rates under Photon.
7. Added 640x400 fullscreen mode emulation via 640x480 (if videodriver not supports original 640x400 mode of course) shifted by 40 vertical pixels from begin, to center it. It's needed for some old DOS games which ran in doubled 320x200 mode.
8. Added available video ram amount support.
8. Added hardware surface allocation/deallocation support if current videomode and videodriver supports it.
9. Added hardware filling support.
10. Added hardware blits support (simple and colorkeyed).

And I've added to testvidinfo test color-keyed blits benchmark (maybe need to add alpha blits benchmark too ?). Currently Photon not supporting any alpha hardware blittings (all drivers lack of alpha blitting code support, only software alpha blitting exist in photon, which is hundreds times slowest than the SDL's one). So I've not added the alpha support. I suppose new QNX 6.3 will have the hardware alpha support, so when it will be done, I'll add alpha support.
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@571
    41
    if (PgGetVideoModeInfo(*(unsigned short*)mode1, &mode_info) < 0)
slouken@571
    42
    {
slouken@571
    43
        return 0;
slouken@571
    44
    }
slouken@0
    45
slouken@571
    46
    key1 = mode_info.width * mode_info.height;
slouken@0
    47
slouken@571
    48
    if (PgGetVideoModeInfo(*(unsigned short*)mode2, &mode_info) < 0)
slouken@571
    49
    {
slouken@571
    50
        return 0;
slouken@571
    51
    }
slouken@0
    52
slouken@571
    53
    key2 = mode_info.width * mode_info.height;
slouken@571
    54
slouken@571
    55
    if (key1 > key2)
slouken@663
    56
    {
slouken@571
    57
        return 1;
slouken@663
    58
    }
slouken@571
    59
    else
slouken@663
    60
    {
slouken@663
    61
        if (key1 == key2)
slouken@663
    62
        {
slouken@663
    63
           return 0;
slouken@663
    64
        }
slouken@663
    65
        else
slouken@663
    66
        {
slouken@663
    67
            return -1;
slouken@663
    68
        }
slouken@663
    69
    }
slouken@0
    70
}
slouken@0
    71
slouken@266
    72
SDL_Rect **ph_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
slouken@0
    73
{
slouken@309
    74
    int i = 0;
slouken@309
    75
    int j = 0;
slouken@309
    76
    SDL_Rect Amodelist[PH_MAX_VIDEOMODES];
slouken@0
    77
slouken@309
    78
    for (i=0; i<PH_MAX_VIDEOMODES; i++)
slouken@309
    79
    {
slouken@309
    80
        SDL_modearray[i]=&SDL_modelist[i];
slouken@309
    81
    }
slouken@309
    82
slouken@821
    83
    if (PgGetVideoModeList(&mode_list) < 0)
slouken@309
    84
    {
slouken@663
    85
       SDL_SetError("ph_ListModes(): PgGetVideoModeList() function failed !\n");
slouken@309
    86
       return NULL;
slouken@309
    87
    }
slouken@309
    88
slouken@309
    89
    mode_info.bits_per_pixel = 0;
slouken@309
    90
slouken@309
    91
    for (i=0; i < mode_list.num_modes; i++) 
slouken@309
    92
    {
slouken@309
    93
        if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0)
slouken@266
    94
        {
slouken@663
    95
            SDL_SetError("ph_ListModes(): PgGetVideoModeInfo() function failed on mode: 0x%X.\n", mode_list.modes[i]);
slouken@309
    96
            return NULL;
slouken@266
    97
        }
slouken@309
    98
        if(mode_info.bits_per_pixel == format->BitsPerPixel)
slouken@309
    99
        {
slouken@309
   100
            Amodelist[j].w = mode_info.width;
slouken@309
   101
            Amodelist[j].h = mode_info.height;
slouken@309
   102
            Amodelist[j].x = 0;
slouken@309
   103
            Amodelist[j].y = 0;
slouken@309
   104
            j++;	
slouken@309
   105
        }
slouken@309
   106
    }
slouken@309
   107
	
slouken@309
   108
    /* reorder biggest for smallest, assume width dominates */
slouken@0
   109
slouken@309
   110
    for(i=0; i<j; i++)
slouken@309
   111
    {
slouken@821
   112
        SDL_modelist[i].w = Amodelist[j - i - 1].w;
slouken@821
   113
        SDL_modelist[i].h = Amodelist[j - i - 1].h;
slouken@821
   114
        SDL_modelist[i].x = Amodelist[j - i - 1].x;
slouken@821
   115
        SDL_modelist[i].y = Amodelist[j - i - 1].y;
slouken@309
   116
    }
slouken@309
   117
    SDL_modearray[j]=NULL;
slouken@0
   118
	
slouken@309
   119
    return SDL_modearray;
slouken@0
   120
}
slouken@0
   121
slouken@0
   122
void ph_FreeVideoModes(_THIS)
slouken@0
   123
{
slouken@266
   124
   return;
slouken@0
   125
}
slouken@0
   126
slouken@309
   127
/* return the mode associated with width, height and bpp */
slouken@309
   128
/* if there is no mode then zero is returned             */
slouken@663
   129
int ph_GetVideoMode(int width, int height, int bpp)
slouken@0
   130
{
slouken@309
   131
    int i;
slouken@821
   132
    int modestage=0;
slouken@821
   133
    int closestmode=0;
slouken@0
   134
slouken@309
   135
    if (PgGetVideoModeList(&mode_list) < 0)
slouken@309
   136
    {
slouken@309
   137
        return -1;
slouken@309
   138
    }
slouken@0
   139
slouken@821
   140
    /* special case for the double-sized 320x200 mode */
slouken@821
   141
    if ((width==640) && (height==400))
slouken@821
   142
    {
slouken@821
   143
       modestage=1;
slouken@821
   144
    }
slouken@821
   145
slouken@309
   146
    /* search list for exact match */
slouken@821
   147
    for (i=0; i<mode_list.num_modes; i++)
slouken@309
   148
    {
slouken@309
   149
        if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0)
slouken@309
   150
        {
slouken@309
   151
            return 0;
slouken@309
   152
        }
slouken@0
   153
slouken@821
   154
        if ((mode_info.width == width) && (mode_info.height == height) && 
slouken@309
   155
            (mode_info.bits_per_pixel == bpp))
slouken@309
   156
        {
slouken@309
   157
            return mode_list.modes[i];
slouken@309
   158
        }
slouken@821
   159
        else
slouken@821
   160
        {
slouken@821
   161
           if ((modestage) && (mode_info.width == width) && (mode_info.height == height+80) && 
slouken@821
   162
               (mode_info.bits_per_pixel == bpp))
slouken@821
   163
           {
slouken@821
   164
              modestage=2;
slouken@821
   165
              closestmode=mode_list.modes[i];
slouken@821
   166
           }
slouken@821
   167
        }
slouken@821
   168
    }
slouken@821
   169
slouken@821
   170
    /* if we are here, then no 640x400xbpp mode found and we'll emulate it via 640x480xbpp mode */
slouken@821
   171
    if (modestage==2)
slouken@821
   172
    {
slouken@821
   173
       return closestmode;
slouken@309
   174
    }
slouken@0
   175
slouken@309
   176
    return (i == mode_list.num_modes) ? 0 : mode_list.modes[i];
slouken@0
   177
}
slouken@0
   178
slouken@821
   179
/* return the mode associated with width, height and bpp               */
slouken@0
   180
/* if requested bpp is not found the mode with closest bpp is returned */
slouken@663
   181
int get_mode_any_format(int width, int height, int bpp)
slouken@0
   182
{
slouken@0
   183
    int i, closest, delta, min_delta;
slouken@0
   184
slouken@663
   185
    if (PgGetVideoModeList(&mode_list) < 0)
slouken@663
   186
    {
slouken@663
   187
        return -1;
slouken@663
   188
    }
slouken@0
   189
slouken@663
   190
    qsort(mode_list.modes, mode_list.num_modes, sizeof(unsigned short), compare_modes_by_res);
slouken@663
   191
slouken@663
   192
    for(i=0;i<mode_list.num_modes;i++)
slouken@663
   193
    {
slouken@663
   194
        if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0)
slouken@663
   195
        {
slouken@663
   196
            return 0;
slouken@663
   197
        }
slouken@663
   198
        if ((mode_info.width == width) && (mode_info.height == height))
slouken@663
   199
        {
slouken@0
   200
           break;
slouken@663
   201
        }
slouken@663
   202
    }
slouken@0
   203
slouken@663
   204
    if (i<mode_list.num_modes)
slouken@663
   205
    {
slouken@663
   206
        /* get closest bpp */
slouken@663
   207
        closest = i++;
slouken@663
   208
        if (mode_info.bits_per_pixel == bpp)
slouken@663
   209
        {
slouken@663
   210
            return mode_list.modes[closest];
slouken@663
   211
        }
slouken@0
   212
slouken@663
   213
        min_delta = abs(mode_info.bits_per_pixel - bpp);
slouken@663
   214
slouken@663
   215
        while(1)
slouken@663
   216
        {
slouken@663
   217
            if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0)
slouken@663
   218
            {
slouken@663
   219
                return 0;
slouken@663
   220
            }
slouken@663
   221
slouken@663
   222
            if ((mode_info.width != width) || (mode_info.height != height))
slouken@663
   223
            {
slouken@663
   224
                break;
slouken@663
   225
            }
slouken@663
   226
            else
slouken@663
   227
            {
slouken@663
   228
                if (mode_info.bits_per_pixel == bpp)
slouken@663
   229
                {
slouken@663
   230
                    closest = i;
slouken@663
   231
                    break;
slouken@663
   232
                }
slouken@663
   233
                else
slouken@663
   234
                {
slouken@663
   235
                    delta = abs(mode_info.bits_per_pixel - bpp);
slouken@663
   236
                    if (delta < min_delta)
slouken@663
   237
                    {
slouken@663
   238
                        closest = i;
slouken@663
   239
                        min_delta = delta;
slouken@663
   240
                    }
slouken@663
   241
                    i++;
slouken@663
   242
                }
slouken@663
   243
            }
slouken@663
   244
        }
slouken@663
   245
        return mode_list.modes[closest];
slouken@663
   246
    }
slouken@663
   247
slouken@309
   248
    return 0;
slouken@0
   249
}
slouken@0
   250
slouken@0
   251
int ph_ToggleFullScreen(_THIS, int on)
slouken@0
   252
{
slouken@663
   253
    return -1;
slouken@0
   254
}
slouken@0
   255
slouken@663
   256
int ph_EnterFullScreen(_THIS, SDL_Surface* screen)
slouken@0
   257
{
slouken@663
   258
    PgDisplaySettings_t settings;
slouken@663
   259
    int mode;
slouken@821
   260
    char* refreshrate;
slouken@821
   261
    int refreshratenum;
slouken@663
   262
slouken@309
   263
    if (!currently_fullscreen)
slouken@309
   264
    {
slouken@663
   265
        /* Get the video mode and set it */
slouken@663
   266
        if (screen->flags & SDL_ANYFORMAT)
slouken@663
   267
        {
slouken@663
   268
            if ((mode = get_mode_any_format(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@663
   273
        }
slouken@663
   274
        else
slouken@663
   275
        {
slouken@663
   276
            if ((mode = ph_GetVideoMode(screen->w, screen->h, screen->format->BitsPerPixel)) == 0)
slouken@663
   277
            {
slouken@663
   278
                SDL_SetError("ph_EnterFullScreen(): can't find appropriate video mode !\n");
slouken@663
   279
                return 0;
slouken@663
   280
            }
slouken@821
   281
            if (PgGetVideoModeInfo(mode, &mode_info) < 0)
slouken@821
   282
            {
slouken@821
   283
                SDL_SetError("ph_EnterFullScreen(): can't get video mode capabilities !\n");
slouken@821
   284
                return 0;
slouken@821
   285
            }
slouken@821
   286
            if (mode_info.height != screen->h)
slouken@821
   287
            {
slouken@821
   288
               if ((mode_info.height==480) && (screen->h==400))
slouken@821
   289
               {
slouken@821
   290
                  videomode_emulatemode=1;
slouken@821
   291
               }
slouken@821
   292
            }
slouken@821
   293
            else
slouken@821
   294
            {
slouken@821
   295
               videomode_emulatemode=0;
slouken@821
   296
            }
slouken@663
   297
        }
slouken@663
   298
slouken@663
   299
        /* save old video mode caps */
slouken@663
   300
        PgGetVideoMode(&settings);
slouken@663
   301
        old_video_mode=settings.mode;
slouken@663
   302
        old_refresh_rate=settings.refresh;
slouken@663
   303
slouken@663
   304
        /* setup new video mode */
slouken@663
   305
        settings.mode = mode;
slouken@663
   306
        settings.refresh = 0;
slouken@663
   307
        settings.flags = 0;
slouken@663
   308
slouken@821
   309
        refreshrate=getenv("SDL_PHOTON_FULLSCREEN_REFRESH");
slouken@821
   310
        if (refreshrate!=NULL)
slouken@821
   311
        {
slouken@821
   312
           if (sscanf(refreshrate, "%d", &refreshratenum)==1)
slouken@821
   313
           {
slouken@821
   314
               settings.refresh = refreshratenum;
slouken@821
   315
           }
slouken@821
   316
        }
slouken@821
   317
slouken@663
   318
        if (PgSetVideoMode(&settings) < 0)
slouken@663
   319
        {
slouken@663
   320
            SDL_SetError("ph_EnterFullScreen(): PgSetVideoMode() call failed !\n");
slouken@663
   321
            return 0;
slouken@663
   322
        }
slouken@663
   323
slouken@315
   324
        if (this->screen)
slouken@309
   325
        {
slouken@315
   326
            if ((this->screen->flags & SDL_OPENGL)==SDL_OPENGL)
slouken@315
   327
            {
slouken@309
   328
#ifdef HAVE_OPENGL
slouken@309
   329
#endif /* HAVE_OPENGL */
slouken@315
   330
                return 0;
slouken@315
   331
            }
slouken@309
   332
        }
slouken@315
   333
slouken@571
   334
        if (OCImage.direct_context==NULL)
slouken@309
   335
        {
slouken@315
   336
            OCImage.direct_context=(PdDirectContext_t*)PdCreateDirectContext();
slouken@663
   337
            if (!OCImage.direct_context)
slouken@663
   338
            {
slouken@663
   339
                SDL_SetError("ph_EnterFullScreen(): Can't create direct context !\n");
slouken@663
   340
                ph_LeaveFullScreen(this);
slouken@663
   341
                return 0;
slouken@663
   342
            }
slouken@315
   343
        }
slouken@0
   344
slouken@571
   345
        OCImage.oldDC=PdDirectStart(OCImage.direct_context);
slouken@0
   346
slouken@315
   347
        currently_fullscreen = 1;
slouken@309
   348
    }
slouken@692
   349
    PgFlush();
slouken@0
   350
slouken@309
   351
    return 1;
slouken@0
   352
}
slouken@0
   353
slouken@315
   354
int ph_LeaveFullScreen(_THIS)
slouken@0
   355
{
slouken@692
   356
    PgDisplaySettings_t oldmode_settings;
slouken@0
   357
       
slouken@309
   358
    if (currently_fullscreen)
slouken@309
   359
    {
slouken@663
   360
        if ((this->screen) && ((this->screen->flags & SDL_OPENGL)==SDL_OPENGL))
slouken@309
   361
        {
slouken@309
   362
#ifdef HAVE_OPENGL
slouken@309
   363
#endif /* HAVE_OPENGL */
slouken@309
   364
           return 0;
slouken@309
   365
        }
slouken@309
   366
        else
slouken@309
   367
        {
slouken@663
   368
            if (OCImage.direct_context)
slouken@663
   369
            {
slouken@663
   370
                PdDirectStop(OCImage.direct_context);
slouken@663
   371
                PdReleaseDirectContext(OCImage.direct_context);
slouken@663
   372
                OCImage.direct_context=NULL;
slouken@663
   373
            }
slouken@663
   374
            if (OCImage.oldDC)
slouken@663
   375
            {
slouken@663
   376
                PhDCSetCurrent(OCImage.oldDC);
slouken@663
   377
                OCImage.oldDC=NULL;
slouken@663
   378
            }
slouken@571
   379
slouken@315
   380
            currently_fullscreen=0;
slouken@0
   381
slouken@309
   382
            /* Restore old video mode */
slouken@309
   383
            if (old_video_mode != -1)
slouken@309
   384
            {
slouken@692
   385
                oldmode_settings.mode = (unsigned short) old_video_mode;
slouken@692
   386
                oldmode_settings.refresh = (unsigned short) old_refresh_rate;
slouken@692
   387
                oldmode_settings.flags = 0;
slouken@315
   388
                
slouken@692
   389
                if (PgSetVideoMode(&oldmode_settings) < 0)
slouken@309
   390
                {
slouken@663
   391
                    SDL_SetError("Ph_LeaveFullScreen(): PgSetVideoMode() function failed !\n");
slouken@571
   392
                    return 0;
slouken@309
   393
                }
slouken@309
   394
            }
slouken@309
   395
slouken@309
   396
            old_video_mode=-1;
slouken@315
   397
            old_refresh_rate=-1;
slouken@309
   398
        }
slouken@309
   399
    }
slouken@309
   400
    return 1;
slouken@0
   401
}