test/testblitspeed.c
author Patrice Mandin <patmandin@gmail.com>
Thu, 19 Jan 2006 21:28:52 +0000
changeset 1257 448a9a64537b
parent 1231 cf59e7b91ed4
child 1658 e49147870aac
child 1895 c121d94672cb
permissions -rw-r--r--
[PATCH] SDL_GetVideoMode() does not find best mode, part 2

Following commit 1.51, I come accross a problem when SDL must choose between
several video modes that could suit the one asked.

If I ask 320x240 with this list:
768x480 768x240 640x400 640x200 384x480 384x240 320x400 320x200

The smallest selectables modes are 384x240 and 320x400. And SDL choose the later
in this list, but 384x240 is more suitable. So I added a check to compare
the pixel count (surface) of modes, and select the one which has the smallest
pixel count.

In my example, 384x240 has 92160 pixels, and 320x400 has 128000 pixels. So now
SDL will choose 384x240 for the asked 320x240 mode.
     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_OPENGLBLIT);
   120         append_sdl_surface_flag(surface, f, sizeof (f), SDL_RESIZABLE);
   121         append_sdl_surface_flag(surface, f, sizeof (f), SDL_NOFRAME);
   122         append_sdl_surface_flag(surface, f, sizeof (f), SDL_HWACCEL);
   123         append_sdl_surface_flag(surface, f, sizeof (f), SDL_SRCCOLORKEY);
   124         append_sdl_surface_flag(surface, f, sizeof (f), SDL_RLEACCELOK);
   125         append_sdl_surface_flag(surface, f, sizeof (f), SDL_RLEACCEL);
   126         append_sdl_surface_flag(surface, f, sizeof (f), SDL_SRCALPHA);
   127         append_sdl_surface_flag(surface, f, sizeof (f), SDL_PREALLOC);
   128 
   129         if (f[0] == '\0')
   130             strcpy(f, " (none)");
   131 
   132         printf("  flags      :%s\n", f);
   133     }
   134 
   135     printf("\n");
   136 }
   137 
   138 static void output_details(void)
   139 {
   140     output_videoinfo_details();
   141     output_surface_details("Source Surface", src);
   142     output_surface_details("Destination Surface", dest);
   143 }
   144 
   145 static Uint32 blit(SDL_Surface *dst, SDL_Surface *src, int x, int y)
   146 {
   147     Uint32 start = 0;
   148     SDL_Rect srcRect;
   149     SDL_Rect dstRect;
   150 
   151     srcRect.x = 0;
   152     srcRect.y = 0;
   153     dstRect.x = x;
   154     dstRect.y = y;
   155     dstRect.w = srcRect.w = src->w;  /* SDL will clip as appropriate. */
   156     dstRect.h = srcRect.h = src->h;
   157 
   158     start = SDL_GetTicks();
   159     SDL_BlitSurface(src, &srcRect, dst, &dstRect);
   160     return(SDL_GetTicks() - start);
   161 }
   162 
   163 static void blitCentered(SDL_Surface *dst, SDL_Surface *src)
   164 {
   165     int x = (dst->w - src->w) / 2;
   166     int y = (dst->h - src->h) / 2;
   167     blit(dst, src, x, y);
   168 }
   169 
   170 static int atoi_hex(const char *str)
   171 {
   172     if (str == NULL)
   173         return 0;
   174 
   175     if (strlen(str) > 2)
   176     {
   177         int retval = 0;
   178         if ((str[0] == '0') && (str[1] == 'x'))
   179             sscanf(str + 2, "%X", &retval);
   180         return(retval);
   181     }
   182 
   183     return(atoi(str));
   184 }
   185 
   186 
   187 static int setup_test(int argc, char **argv)
   188 {
   189     const char *dumpfile = NULL;
   190     SDL_Surface *bmp = NULL;
   191     Uint32 dstbpp = 32;
   192     Uint32 dstrmask = 0x00FF0000;
   193     Uint32 dstgmask = 0x0000FF00;
   194     Uint32 dstbmask = 0x000000FF;
   195     Uint32 dstamask = 0x00000000;
   196     Uint32 dstflags = 0;
   197     int dstw = 640;
   198     int dsth = 480;
   199     Uint32 srcbpp = 32;
   200     Uint32 srcrmask = 0x00FF0000;
   201     Uint32 srcgmask = 0x0000FF00;
   202     Uint32 srcbmask = 0x000000FF;
   203     Uint32 srcamask = 0x00000000;
   204     Uint32 srcflags = 0;
   205     int srcw = 640;
   206     int srch = 480;
   207     Uint32 origsrcalphaflags = 0;
   208     Uint32 origdstalphaflags = 0;
   209     Uint32 srcalphaflags = 0;
   210     Uint32 dstalphaflags = 0;
   211     int srcalpha = 255;
   212     int dstalpha = 255;
   213     int screenSurface = 0;
   214     int i = 0;
   215 
   216     for (i = 1; i < argc; i++)
   217     {
   218         const char *arg = argv[i];
   219 
   220         if (strcmp(arg, "--dstbpp") == 0)
   221             dstbpp = atoi(argv[++i]);
   222         else if (strcmp(arg, "--dstrmask") == 0)
   223             dstrmask = atoi_hex(argv[++i]);
   224         else if (strcmp(arg, "--dstgmask") == 0)
   225             dstgmask = atoi_hex(argv[++i]);
   226         else if (strcmp(arg, "--dstbmask") == 0)
   227             dstbmask = atoi_hex(argv[++i]);
   228         else if (strcmp(arg, "--dstamask") == 0)
   229             dstamask = atoi_hex(argv[++i]);
   230         else if (strcmp(arg, "--dstwidth") == 0)
   231             dstw = atoi(argv[++i]);
   232         else if (strcmp(arg, "--dstheight") == 0)
   233             dsth = atoi(argv[++i]);
   234         else if (strcmp(arg, "--dsthwsurface") == 0)
   235             dstflags |= SDL_HWSURFACE;
   236         else if (strcmp(arg, "--srcbpp") == 0)
   237             srcbpp = atoi(argv[++i]);
   238         else if (strcmp(arg, "--srcrmask") == 0)
   239             srcrmask = atoi_hex(argv[++i]);
   240         else if (strcmp(arg, "--srcgmask") == 0)
   241             srcgmask = atoi_hex(argv[++i]);
   242         else if (strcmp(arg, "--srcbmask") == 0)
   243             srcbmask = atoi_hex(argv[++i]);
   244         else if (strcmp(arg, "--srcamask") == 0)
   245             srcamask = atoi_hex(argv[++i]);
   246         else if (strcmp(arg, "--srcwidth") == 0)
   247             srcw = atoi(argv[++i]);
   248         else if (strcmp(arg, "--srcheight") == 0)
   249             srch = atoi(argv[++i]);
   250         else if (strcmp(arg, "--srchwsurface") == 0)
   251             srcflags |= SDL_HWSURFACE;
   252         else if (strcmp(arg, "--seconds") == 0)
   253             testSeconds = atoi(argv[++i]);
   254         else if (strcmp(arg, "--screen") == 0)
   255             screenSurface = 1;
   256         else if (strcmp(arg, "--dumpfile") == 0)
   257             dumpfile = argv[++i];
   258         /* !!! FIXME: set colorkey. */
   259         else if (0)  /* !!! FIXME: we handle some commandlines elsewhere now */
   260         {
   261             fprintf(stderr, "Unknown commandline option: %s\n", arg);
   262             return(0);
   263         }
   264     }
   265 
   266     if (SDL_Init(SDL_INIT_VIDEO) == -1)
   267     {
   268         fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError());
   269         return(0);
   270     }
   271 
   272     bmp = SDL_LoadBMP("sample.bmp");
   273     if (bmp == NULL)
   274     {
   275         fprintf(stderr, "SDL_LoadBMP failed: %s\n", SDL_GetError());
   276         SDL_Quit();
   277         return(0);
   278     }
   279 
   280     if ((dstflags & SDL_HWSURFACE) == 0) dstflags |= SDL_SWSURFACE;
   281     if ((srcflags & SDL_HWSURFACE) == 0) srcflags |= SDL_SWSURFACE;
   282 
   283     if (screenSurface)
   284         dest = SDL_SetVideoMode(dstw, dsth, dstbpp, dstflags);
   285     else
   286     {
   287         dest = SDL_CreateRGBSurface(dstflags, dstw, dsth, dstbpp,
   288                                     dstrmask, dstgmask, dstbmask, dstamask);
   289     }
   290 
   291     if (dest == NULL)
   292     {
   293         fprintf(stderr, "dest surface creation failed: %s\n", SDL_GetError());
   294         SDL_Quit();
   295         return(0);
   296     }
   297 
   298     src = SDL_CreateRGBSurface(srcflags, srcw, srch, srcbpp,
   299                                srcrmask, srcgmask, srcbmask, srcamask);
   300     if (src == NULL)
   301     {
   302         fprintf(stderr, "src surface creation failed: %s\n", SDL_GetError());
   303         SDL_Quit();
   304         return(0);
   305     }
   306 
   307     /* handle alpha settings... */
   308     srcalphaflags = (src->flags&SDL_SRCALPHA) | (src->flags&SDL_RLEACCEL);
   309     dstalphaflags = (dest->flags&SDL_SRCALPHA) | (dest->flags&SDL_RLEACCEL);
   310     origsrcalphaflags = srcalphaflags;
   311     origdstalphaflags = dstalphaflags;
   312     srcalpha = src->format->alpha;
   313     dstalpha = dest->format->alpha;
   314     for (i = 1; i < argc; i++)
   315     {
   316         const char *arg = argv[i];
   317 
   318         if (strcmp(arg, "--srcalpha") == 0)
   319             srcalpha = atoi(argv[++i]);
   320         else if (strcmp(arg, "--dstalpha") == 0)
   321             dstalpha = atoi(argv[++i]);
   322         else if (strcmp(arg, "--srcsrcalpha") == 0)
   323             srcalphaflags |= SDL_SRCALPHA;
   324         else if (strcmp(arg, "--srcnosrcalpha") == 0)
   325             srcalphaflags &= ~SDL_SRCALPHA;
   326         else if (strcmp(arg, "--srcrleaccel") == 0)
   327             srcalphaflags |= SDL_RLEACCEL;
   328         else if (strcmp(arg, "--srcnorleaccel") == 0)
   329             srcalphaflags &= ~SDL_RLEACCEL;
   330         else if (strcmp(arg, "--dstsrcalpha") == 0)
   331             dstalphaflags |= SDL_SRCALPHA;
   332         else if (strcmp(arg, "--dstnosrcalpha") == 0)
   333             dstalphaflags &= ~SDL_SRCALPHA;
   334         else if (strcmp(arg, "--dstrleaccel") == 0)
   335             dstalphaflags |= SDL_RLEACCEL;
   336         else if (strcmp(arg, "--dstnorleaccel") == 0)
   337             dstalphaflags &= ~SDL_RLEACCEL;
   338     }
   339     if ((dstalphaflags != origdstalphaflags) || (dstalpha != dest->format->alpha))
   340         SDL_SetAlpha(dest, dstalphaflags, (Uint8) dstalpha);
   341     if ((srcalphaflags != origsrcalphaflags) || (srcalpha != src->format->alpha))
   342         SDL_SetAlpha(src, srcalphaflags, (Uint8) srcalpha);
   343 
   344     /* set some sane defaults so we can see if the blit code is broken... */
   345     SDL_FillRect(dest, NULL, SDL_MapRGB(dest->format, 0, 0, 0));
   346     SDL_FillRect(src, NULL, SDL_MapRGB(src->format, 0, 0, 0));
   347 
   348     blitCentered(src, bmp);
   349     SDL_FreeSurface(bmp);
   350 
   351     if (dumpfile)
   352         SDL_SaveBMP(src, dumpfile);  /* make sure initial convert is sane. */
   353 
   354     output_details();
   355 
   356     return(1);
   357 }
   358 
   359 
   360 static void test_blit_speed(void)
   361 {
   362     Uint32 clearColor = SDL_MapRGB(dest->format, 0, 0, 0);
   363     Uint32 iterations = 0;
   364     Uint32 elasped = 0;
   365     Uint32 end = 0;
   366     Uint32 now = 0;
   367     Uint32 last = 0;
   368     int testms = testSeconds * 1000;
   369     int wmax = (dest->w - src->w);
   370     int hmax = (dest->h - src->h);
   371     int isScreen = (SDL_GetVideoSurface() == dest);
   372     SDL_Event event;
   373 
   374     printf("Testing blit speed for %d seconds...\n", testSeconds);
   375 
   376     now = SDL_GetTicks();
   377     end = now + testms;
   378 
   379     do
   380     {
   381         /* pump the event queue occasionally to keep OS happy... */
   382         if (now - last > 1000)
   383         {
   384             last = now;
   385             while (SDL_PollEvent(&event)) { /* no-op. */ }
   386         }
   387 
   388         iterations++;
   389         elasped += blit(dest, src, randRange(0, wmax), randRange(0, hmax));
   390         if (isScreen)
   391         {
   392             SDL_Flip(dest);  /* show it! */
   393             SDL_FillRect(dest, NULL, clearColor); /* blank it for next time! */
   394         }
   395 
   396         now = SDL_GetTicks();
   397     } while (now < end);
   398 
   399     printf("Non-blitting crap accounted for %d percent of this run.\n",
   400             percent(testms - elasped, testms));
   401 
   402     printf("%d blits took %d ms (%d fps).\n",
   403             (int) iterations,
   404             (int) elasped,
   405             (int) (((float)iterations) / (((float)elasped) / 1000.0f)));
   406 }
   407 
   408 int main(int argc, char **argv)
   409 {
   410     int initialized = setup_test(argc, argv);
   411     if (initialized)
   412     {
   413         test_blit_speed();
   414         SDL_Quit();
   415     }
   416     return(!initialized);
   417 }
   418 
   419 /* end of testblitspeed.c ... */
   420