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