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