test/testblitspeed.c
author Ryan C. Gordon <icculus@icculus.org>
Thu, 29 Sep 2005 09:43:00 +0000
changeset 1152 51a8702d8ecd
parent 1039 68f2b997758e
child 1231 cf59e7b91ed4
permissions -rw-r--r--
Updates to PocketPC (WinCE) support, thanks to Dmitry Yakimov at
activekitten.com.
icculus@1039
     1
/*
icculus@1039
     2
 * Benchmarks surface-to-surface blits in various formats.
icculus@1039
     3
 *
icculus@1039
     4
 *  Written by Ryan C. Gordon.
icculus@1039
     5
 */
icculus@1039
     6
icculus@1039
     7
#include <stdio.h>
icculus@1039
     8
#include <stdlib.h>
icculus@1039
     9
#include <string.h>
icculus@1039
    10
icculus@1039
    11
#include "SDL.h"
icculus@1039
    12
icculus@1039
    13
static SDL_Surface *dest = NULL;
icculus@1039
    14
static SDL_Surface *src = NULL;
icculus@1039
    15
static int testSeconds = 10;
icculus@1039
    16
icculus@1039
    17
icculus@1039
    18
static int percent(int val, int total)
icculus@1039
    19
{
icculus@1039
    20
    return((int) ((((float) val) / ((float) total)) * 100.0f));
icculus@1039
    21
}
icculus@1039
    22
icculus@1039
    23
static int randRange(int lo, int hi)
icculus@1039
    24
{
icculus@1039
    25
    return(lo + (int) (((double) hi)*rand()/(RAND_MAX+1.0)));
icculus@1039
    26
}
icculus@1039
    27
icculus@1039
    28
static void copy_trunc_str(char *str, size_t strsize, const char *flagstr)
icculus@1039
    29
{
icculus@1039
    30
    if ( (strlen(str) + strlen(flagstr)) >= (strsize - 1) )
icculus@1039
    31
        strcpy(str + (strsize - 5), " ...");
icculus@1039
    32
    else
icculus@1039
    33
        strcat(str, flagstr);
icculus@1039
    34
}
icculus@1039
    35
icculus@1039
    36
static void __append_sdl_surface_flag(SDL_Surface *_surface, char *str,
icculus@1039
    37
                                      size_t strsize, Uint32 flag,
icculus@1039
    38
                                      const char *flagstr)
icculus@1039
    39
{
icculus@1039
    40
    if (_surface->flags & flag)
icculus@1039
    41
        copy_trunc_str(str, strsize, flagstr);
icculus@1039
    42
} /* append_sdl_surface_flag */
icculus@1039
    43
icculus@1039
    44
icculus@1039
    45
#define append_sdl_surface_flag(a, b, c, fl) __append_sdl_surface_flag(a, b, c, fl, " " #fl)
icculus@1039
    46
#define print_tf_state(str, val) printf("%s: {%s}\n", str, (val) ? "true" : "false" )
icculus@1039
    47
icculus@1039
    48
static void output_surface_details(const char *name, SDL_Surface *surface)
icculus@1039
    49
{
icculus@1039
    50
    printf("Details for %s:\n", name);
icculus@1039
    51
icculus@1039
    52
    if (surface == NULL)
icculus@1039
    53
    {
icculus@1039
    54
        printf("-WARNING- You've got a NULL surface!");
icculus@1039
    55
    }
icculus@1039
    56
    else
icculus@1039
    57
    {
icculus@1039
    58
        char f[256];
icculus@1039
    59
        printf("  width  : %d\n", surface->w);
icculus@1039
    60
        printf("  height : %d\n", surface->h);
icculus@1039
    61
        printf("  depth  : %d bits per pixel\n", surface->format->BitsPerPixel);
icculus@1039
    62
        printf("  pitch  : %d\n", (int) surface->pitch);
icculus@1039
    63
icculus@1039
    64
        printf("  red    : 0x%08X mask, %d shift, %d loss\n",
icculus@1039
    65
                    (int) surface->format->Rmask,
icculus@1039
    66
                    (int) surface->format->Rshift,
icculus@1039
    67
                    (int) surface->format->Rloss);
icculus@1039
    68
        printf("  green  : 0x%08X mask, %d shift, %d loss\n",
icculus@1039
    69
                    (int) surface->format->Gmask,
icculus@1039
    70
                    (int) surface->format->Gshift,
icculus@1039
    71
                    (int) surface->format->Gloss);
icculus@1039
    72
        printf("  blue   : 0x%08X mask, %d shift, %d loss\n",
icculus@1039
    73
                    (int) surface->format->Bmask,
icculus@1039
    74
                    (int) surface->format->Bshift,
icculus@1039
    75
                    (int) surface->format->Bloss);
icculus@1039
    76
        printf("  alpha  : 0x%08X mask, %d shift, %d loss\n",
icculus@1039
    77
                    (int) surface->format->Amask,
icculus@1039
    78
                    (int) surface->format->Ashift,
icculus@1039
    79
                    (int) surface->format->Aloss);
icculus@1039
    80
icculus@1039
    81
        f[0] = '\0';
icculus@1039
    82
icculus@1039
    83
        /*append_sdl_surface_flag(surface, f, sizeof (f), SDL_SWSURFACE);*/
icculus@1039
    84
        if ((surface->flags & SDL_HWSURFACE) == 0)
icculus@1039
    85
            copy_trunc_str(f, sizeof (f), " SDL_SWSURFACE");
icculus@1039
    86
icculus@1039
    87
        append_sdl_surface_flag(surface, f, sizeof (f), SDL_HWSURFACE);
icculus@1039
    88
        append_sdl_surface_flag(surface, f, sizeof (f), SDL_ASYNCBLIT);
icculus@1039
    89
        append_sdl_surface_flag(surface, f, sizeof (f), SDL_ANYFORMAT);
icculus@1039
    90
        append_sdl_surface_flag(surface, f, sizeof (f), SDL_HWPALETTE);
icculus@1039
    91
        append_sdl_surface_flag(surface, f, sizeof (f), SDL_DOUBLEBUF);
icculus@1039
    92
        append_sdl_surface_flag(surface, f, sizeof (f), SDL_FULLSCREEN);
icculus@1039
    93
        append_sdl_surface_flag(surface, f, sizeof (f), SDL_OPENGL);
icculus@1039
    94
        append_sdl_surface_flag(surface, f, sizeof (f), SDL_OPENGLBLIT);
icculus@1039
    95
        append_sdl_surface_flag(surface, f, sizeof (f), SDL_RESIZABLE);
icculus@1039
    96
        append_sdl_surface_flag(surface, f, sizeof (f), SDL_NOFRAME);
icculus@1039
    97
        append_sdl_surface_flag(surface, f, sizeof (f), SDL_HWACCEL);
icculus@1039
    98
        append_sdl_surface_flag(surface, f, sizeof (f), SDL_SRCCOLORKEY);
icculus@1039
    99
        append_sdl_surface_flag(surface, f, sizeof (f), SDL_RLEACCELOK);
icculus@1039
   100
        append_sdl_surface_flag(surface, f, sizeof (f), SDL_RLEACCEL);
icculus@1039
   101
        append_sdl_surface_flag(surface, f, sizeof (f), SDL_SRCALPHA);
icculus@1039
   102
        append_sdl_surface_flag(surface, f, sizeof (f), SDL_PREALLOC);
icculus@1039
   103
icculus@1039
   104
        if (f[0] == '\0')
icculus@1039
   105
            strcpy(f, " (none)");
icculus@1039
   106
icculus@1039
   107
        printf("  flags  :%s\n", f);
icculus@1039
   108
icculus@1039
   109
        #if 0
icculus@1039
   110
        info = SDL_GetVideoInfo();
icculus@1039
   111
        assert(info != NULL);
icculus@1039
   112
icculus@1039
   113
        print_tf_state("hardware surface available", info->hw_available);
icculus@1039
   114
        print_tf_state("window manager available", info->wm_available);
icculus@1039
   115
        print_tf_state("accelerated hardware->hardware blits", info->blit_hw);
icculus@1039
   116
        print_tf_state("accelerated hardware->hardware colorkey blits", info->blit_hw_CC);
icculus@1039
   117
        print_tf_state("accelerated hardware->hardware alpha blits", info->blit_hw_A);
icculus@1039
   118
        print_tf_state("accelerated software->hardware blits", info->blit_sw);
icculus@1039
   119
        print_tf_state("accelerated software->hardware colorkey blits", info->blit_sw_CC);
icculus@1039
   120
        print_tf_state("accelerated software->hardware alpha blits", info->blit_sw_A);
icculus@1039
   121
        print_tf_state("accelerated color fills", info->blit_fill);
icculus@1039
   122
icculus@1039
   123
        printf("video memory: (%d)\n", info->video_mem);
icculus@1039
   124
        #endif
icculus@1039
   125
    } /* else */
icculus@1039
   126
icculus@1039
   127
    printf("\n");
icculus@1039
   128
}
icculus@1039
   129
icculus@1039
   130
static void output_details(void)
icculus@1039
   131
{
icculus@1039
   132
    output_surface_details("Source Surface", src);
icculus@1039
   133
    output_surface_details("Destination Surface", dest);
icculus@1039
   134
}
icculus@1039
   135
icculus@1039
   136
static Uint32 blit(SDL_Surface *dst, SDL_Surface *src, int x, int y)
icculus@1039
   137
{
icculus@1039
   138
    Uint32 start = 0;
icculus@1039
   139
    SDL_Rect srcRect;
icculus@1039
   140
    SDL_Rect dstRect;
icculus@1039
   141
icculus@1039
   142
    srcRect.x = 0;
icculus@1039
   143
    srcRect.y = 0;
icculus@1039
   144
    dstRect.x = x;
icculus@1039
   145
    dstRect.y = y;
icculus@1039
   146
    dstRect.w = srcRect.w = src->w;  /* SDL will clip as appropriate. */
icculus@1039
   147
    dstRect.h = srcRect.h = src->h;
icculus@1039
   148
icculus@1039
   149
    start = SDL_GetTicks();
icculus@1039
   150
    SDL_BlitSurface(src, &srcRect, dst, &dstRect);
icculus@1039
   151
    return(SDL_GetTicks() - start);
icculus@1039
   152
}
icculus@1039
   153
icculus@1039
   154
static void blitCentered(SDL_Surface *dst, SDL_Surface *src)
icculus@1039
   155
{
icculus@1039
   156
    int x = (dst->w - src->w) / 2;
icculus@1039
   157
    int y = (dst->h - src->h) / 2;
icculus@1039
   158
    blit(dst, src, x, y);
icculus@1039
   159
}
icculus@1039
   160
icculus@1039
   161
static int atoi_hex(const char *str)
icculus@1039
   162
{
icculus@1039
   163
    if (str == NULL)
icculus@1039
   164
        return 0;
icculus@1039
   165
icculus@1039
   166
    if (strlen(str) > 2)
icculus@1039
   167
    {
icculus@1039
   168
        int retval = 0;
icculus@1039
   169
        if ((str[0] == '0') && (str[1] == 'x'))
icculus@1039
   170
            sscanf(str + 2, "%X", &retval);
icculus@1039
   171
        return(retval);
icculus@1039
   172
    }
icculus@1039
   173
icculus@1039
   174
    return(atoi(str));
icculus@1039
   175
}
icculus@1039
   176
icculus@1039
   177
icculus@1039
   178
static int setup_test(int argc, char **argv)
icculus@1039
   179
{
icculus@1039
   180
    const char *dumpfile = NULL;
icculus@1039
   181
    SDL_Surface *bmp = NULL;
icculus@1039
   182
    Uint32 dstbpp = 32;
icculus@1039
   183
    Uint32 dstrmask = 0x00FF0000;
icculus@1039
   184
    Uint32 dstgmask = 0x0000FF00;
icculus@1039
   185
    Uint32 dstbmask = 0x000000FF;
icculus@1039
   186
    Uint32 dstamask = 0x00000000;
icculus@1039
   187
    Uint32 dstflags = 0;
icculus@1039
   188
    int dstw = 640;
icculus@1039
   189
    int dsth = 480;
icculus@1039
   190
    Uint32 srcbpp = 32;
icculus@1039
   191
    Uint32 srcrmask = 0x00FF0000;
icculus@1039
   192
    Uint32 srcgmask = 0x0000FF00;
icculus@1039
   193
    Uint32 srcbmask = 0x000000FF;
icculus@1039
   194
    Uint32 srcamask = 0x00000000;
icculus@1039
   195
    Uint32 srcflags = 0;
icculus@1039
   196
    int srcw = 640;
icculus@1039
   197
    int srch = 480;
icculus@1039
   198
    int screenSurface = 0;
icculus@1039
   199
    int i;
icculus@1039
   200
icculus@1039
   201
    for (i = 1; i < argc; i++)
icculus@1039
   202
    {
icculus@1039
   203
        const char *arg = argv[i];
icculus@1039
   204
icculus@1039
   205
        if (strcmp(arg, "--dstbpp") == 0)
icculus@1039
   206
            dstbpp = atoi(argv[++i]);
icculus@1039
   207
        else if (strcmp(arg, "--dstrmask") == 0)
icculus@1039
   208
            dstrmask = atoi_hex(argv[++i]);
icculus@1039
   209
        else if (strcmp(arg, "--dstgmask") == 0)
icculus@1039
   210
            dstgmask = atoi_hex(argv[++i]);
icculus@1039
   211
        else if (strcmp(arg, "--dstbmask") == 0)
icculus@1039
   212
            dstbmask = atoi_hex(argv[++i]);
icculus@1039
   213
        else if (strcmp(arg, "--dstamask") == 0)
icculus@1039
   214
            dstamask = atoi_hex(argv[++i]);
icculus@1039
   215
        else if (strcmp(arg, "--dstwidth") == 0)
icculus@1039
   216
            dstw = atoi(argv[++i]);
icculus@1039
   217
        else if (strcmp(arg, "--dstheight") == 0)
icculus@1039
   218
            dsth = atoi(argv[++i]);
icculus@1039
   219
        else if (strcmp(arg, "--dsthwsurface") == 0)
icculus@1039
   220
            dstflags |= SDL_HWSURFACE;
icculus@1039
   221
        else if (strcmp(arg, "--srcbpp") == 0)
icculus@1039
   222
            srcbpp = atoi(argv[++i]);
icculus@1039
   223
        else if (strcmp(arg, "--srcrmask") == 0)
icculus@1039
   224
            srcrmask = atoi_hex(argv[++i]);
icculus@1039
   225
        else if (strcmp(arg, "--srcgmask") == 0)
icculus@1039
   226
            srcgmask = atoi_hex(argv[++i]);
icculus@1039
   227
        else if (strcmp(arg, "--srcbmask") == 0)
icculus@1039
   228
            srcbmask = atoi_hex(argv[++i]);
icculus@1039
   229
        else if (strcmp(arg, "--srcamask") == 0)
icculus@1039
   230
            srcamask = atoi_hex(argv[++i]);
icculus@1039
   231
        else if (strcmp(arg, "--srcwidth") == 0)
icculus@1039
   232
            srcw = atoi(argv[++i]);
icculus@1039
   233
        else if (strcmp(arg, "--srcheight") == 0)
icculus@1039
   234
            srch = atoi(argv[++i]);
icculus@1039
   235
        else if (strcmp(arg, "--srchwsurface") == 0)
icculus@1039
   236
            srcflags |= SDL_HWSURFACE;
icculus@1039
   237
        else if (strcmp(arg, "--seconds") == 0)
icculus@1039
   238
            testSeconds = atoi(argv[++i]);
icculus@1039
   239
        else if (strcmp(arg, "--screen") == 0)
icculus@1039
   240
            screenSurface = 1;
icculus@1039
   241
        else if (strcmp(arg, "--dumpfile") == 0)
icculus@1039
   242
            dumpfile = argv[++i];
icculus@1039
   243
        else
icculus@1039
   244
        {
icculus@1039
   245
            fprintf(stderr, "Unknown commandline option: %s\n", arg);
icculus@1039
   246
            return(0);
icculus@1039
   247
        }
icculus@1039
   248
    }
icculus@1039
   249
icculus@1039
   250
    if (SDL_Init(SDL_INIT_VIDEO) == -1)
icculus@1039
   251
    {
icculus@1039
   252
        fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError());
icculus@1039
   253
        return(0);
icculus@1039
   254
    }
icculus@1039
   255
icculus@1039
   256
    bmp = SDL_LoadBMP("sample.bmp");
icculus@1039
   257
    if (bmp == NULL)
icculus@1039
   258
    {
icculus@1039
   259
        fprintf(stderr, "SDL_LoadBMP failed: %s\n", SDL_GetError());
icculus@1039
   260
        SDL_Quit();
icculus@1039
   261
        return(0);
icculus@1039
   262
    }
icculus@1039
   263
icculus@1039
   264
    if ((dstflags & SDL_HWSURFACE) == 0) dstflags |= SDL_SWSURFACE;
icculus@1039
   265
    if ((srcflags & SDL_HWSURFACE) == 0) srcflags |= SDL_SWSURFACE;
icculus@1039
   266
icculus@1039
   267
    if (screenSurface)
icculus@1039
   268
        dest = SDL_SetVideoMode(dstw, dsth, dstbpp, dstflags);
icculus@1039
   269
    else
icculus@1039
   270
    {
icculus@1039
   271
        dest = SDL_CreateRGBSurface(dstflags, dstw, dsth, dstbpp,
icculus@1039
   272
                                    dstrmask, dstgmask, dstbmask, dstamask);
icculus@1039
   273
    }
icculus@1039
   274
icculus@1039
   275
    if (dest == NULL)
icculus@1039
   276
    {
icculus@1039
   277
        fprintf(stderr, "dest surface creation failed: %s\n", SDL_GetError());
icculus@1039
   278
        SDL_Quit();
icculus@1039
   279
        return(0);
icculus@1039
   280
    }
icculus@1039
   281
icculus@1039
   282
    src = SDL_CreateRGBSurface(srcflags, srcw, srch, srcbpp,
icculus@1039
   283
                               srcrmask, srcgmask, srcbmask, srcamask);
icculus@1039
   284
    if (src == NULL)
icculus@1039
   285
    {
icculus@1039
   286
        fprintf(stderr, "src surface creation failed: %s\n", SDL_GetError());
icculus@1039
   287
        SDL_Quit();
icculus@1039
   288
        return(0);
icculus@1039
   289
    }
icculus@1039
   290
icculus@1039
   291
    /* set some sane defaults so we can see if the blit code is broken... */
icculus@1039
   292
    SDL_FillRect(dest, NULL, SDL_MapRGB(dest->format, 0, 0, 0));
icculus@1039
   293
    SDL_FillRect(src, NULL, SDL_MapRGB(src->format, 0, 0, 0));
icculus@1039
   294
icculus@1039
   295
    blitCentered(src, bmp);
icculus@1039
   296
    SDL_FreeSurface(bmp);
icculus@1039
   297
icculus@1039
   298
    if (dumpfile)
icculus@1039
   299
        SDL_SaveBMP(src, dumpfile);  /* make sure initial convert is sane. */
icculus@1039
   300
icculus@1039
   301
    output_details();
icculus@1039
   302
icculus@1039
   303
    return(1);
icculus@1039
   304
}
icculus@1039
   305
icculus@1039
   306
icculus@1039
   307
static void test_blit_speed(void)
icculus@1039
   308
{
icculus@1039
   309
    Uint32 clearColor = SDL_MapRGB(dest->format, 0, 0, 0);
icculus@1039
   310
    Uint32 iterations = 0;
icculus@1039
   311
    Uint32 elasped = 0;
icculus@1039
   312
    Uint32 end = 0;
icculus@1039
   313
    Uint32 now = 0;
icculus@1039
   314
    Uint32 last = 0;
icculus@1039
   315
    int testms = testSeconds * 1000;
icculus@1039
   316
    int wmax = (dest->w - src->w);
icculus@1039
   317
    int hmax = (dest->h - src->h);
icculus@1039
   318
    int isScreen = (SDL_GetVideoSurface() == dest);
icculus@1039
   319
    SDL_Event event;
icculus@1039
   320
icculus@1039
   321
    printf("Testing blit speed for %d seconds...\n", testSeconds);
icculus@1039
   322
icculus@1039
   323
    now = SDL_GetTicks();
icculus@1039
   324
    end = now + testms;
icculus@1039
   325
icculus@1039
   326
    do
icculus@1039
   327
    {
icculus@1039
   328
        /* pump the event queue occasionally to keep OS happy... */
icculus@1039
   329
        if (now - last > 1000)
icculus@1039
   330
        {
icculus@1039
   331
            last = now;
icculus@1039
   332
            while (SDL_PollEvent(&event)) { /* no-op. */ }
icculus@1039
   333
        }
icculus@1039
   334
icculus@1039
   335
        iterations++;
icculus@1039
   336
        elasped += blit(dest, src, randRange(0, wmax), randRange(0, hmax));
icculus@1039
   337
        if (isScreen)
icculus@1039
   338
        {
icculus@1039
   339
            SDL_Flip(dest);  /* show it! */
icculus@1039
   340
            SDL_FillRect(dest, NULL, clearColor); /* blank it for next time! */
icculus@1039
   341
        }
icculus@1039
   342
icculus@1039
   343
        now = SDL_GetTicks();
icculus@1039
   344
    } while (now < end);
icculus@1039
   345
icculus@1039
   346
    printf("Non-blitting crap accounted for %d percent of this run.\n",
icculus@1039
   347
            percent(testms - elasped, testms));
icculus@1039
   348
icculus@1039
   349
    printf("%d blits took %d ms (%d fps).\n",
icculus@1039
   350
            (int) iterations,
icculus@1039
   351
            (int) elasped,
icculus@1039
   352
            (int) (((float)iterations) / (((float)elasped) / 1000.0f)));
icculus@1039
   353
}
icculus@1039
   354
icculus@1039
   355
int main(int argc, char **argv)
icculus@1039
   356
{
icculus@1039
   357
    int initialized = setup_test(argc, argv);
icculus@1039
   358
    if (initialized)
icculus@1039
   359
    {
icculus@1039
   360
        test_blit_speed();
icculus@1039
   361
        SDL_Quit();
icculus@1039
   362
    }
icculus@1039
   363
    return(!initialized);
icculus@1039
   364
}
icculus@1039
   365
icculus@1039
   366
/* end of testblitspeed.c ... */
icculus@1039
   367