/* * Benchmarks surface-to-surface blits in various formats. * * Written by Ryan C. Gordon. */ #include #include #include #include "SDL.h" static SDL_Surface *dest = NULL; static SDL_Surface *src = NULL; static int testSeconds = 10; static int percent (int val, int total) { return ((int) ((((float) val) / ((float) total)) * 100.0f)); } static int randRange (int lo, int hi) { return (lo + (int) (((double) hi) * rand () / (RAND_MAX + 1.0))); } static void copy_trunc_str (char *str, size_t strsize, const char *flagstr) { if ((strlen (str) + strlen (flagstr)) >= (strsize - 1)) strcpy (str + (strsize - 5), " ..."); else strcat (str, flagstr); } static void __append_sdl_surface_flag (SDL_Surface * _surface, char *str, size_t strsize, Uint32 flag, const char *flagstr) { if (_surface->flags & flag) copy_trunc_str (str, strsize, flagstr); } #define append_sdl_surface_flag(a, b, c, fl) __append_sdl_surface_flag(a, b, c, fl, " " #fl) #define print_tf_state(str, val) printf("%s: {%s}\n", str, (val) ? "true" : "false" ) static void output_videoinfo_details (void) { const SDL_VideoInfo *info = SDL_GetVideoInfo (); printf ("SDL_GetVideoInfo():\n"); if (info == NULL) printf (" (null.)\n"); else { print_tf_state (" hardware surface available", info->hw_available); print_tf_state (" window manager available", info->wm_available); print_tf_state (" accelerated hardware->hardware blits", info->blit_hw); print_tf_state (" accelerated hardware->hardware colorkey blits", info->blit_hw_CC); print_tf_state (" accelerated hardware->hardware alpha blits", info->blit_hw_A); print_tf_state (" accelerated software->hardware blits", info->blit_sw); print_tf_state (" accelerated software->hardware colorkey blits", info->blit_sw_CC); print_tf_state (" accelerated software->hardware alpha blits", info->blit_sw_A); print_tf_state (" accelerated color fills", info->blit_fill); printf (" video memory: (%d)\n", info->video_mem); } printf ("\n"); } static void output_surface_details (const char *name, SDL_Surface * surface) { printf ("Details for %s:\n", name); if (surface == NULL) { printf ("-WARNING- You've got a NULL surface!"); } else { char f[256]; printf (" width : %d\n", surface->w); printf (" height : %d\n", surface->h); printf (" depth : %d bits per pixel\n", surface->format->BitsPerPixel); printf (" pitch : %d\n", (int) surface->pitch); printf (" alpha : %d\n", (int) surface->format->alpha); printf (" colorkey : 0x%X\n", (unsigned int) surface->format->colorkey); printf (" red bits : 0x%08X mask, %d shift, %d loss\n", (int) surface->format->Rmask, (int) surface->format->Rshift, (int) surface->format->Rloss); printf (" green bits : 0x%08X mask, %d shift, %d loss\n", (int) surface->format->Gmask, (int) surface->format->Gshift, (int) surface->format->Gloss); printf (" blue bits : 0x%08X mask, %d shift, %d loss\n", (int) surface->format->Bmask, (int) surface->format->Bshift, (int) surface->format->Bloss); printf (" alpha bits : 0x%08X mask, %d shift, %d loss\n", (int) surface->format->Amask, (int) surface->format->Ashift, (int) surface->format->Aloss); f[0] = '\0'; /*append_sdl_surface_flag(surface, f, sizeof (f), SDL_SWSURFACE); */ if ((surface->flags & SDL_HWSURFACE) == 0) copy_trunc_str (f, sizeof (f), " SDL_SWSURFACE"); append_sdl_surface_flag (surface, f, sizeof (f), SDL_HWSURFACE); append_sdl_surface_flag (surface, f, sizeof (f), SDL_ASYNCBLIT); append_sdl_surface_flag (surface, f, sizeof (f), SDL_ANYFORMAT); append_sdl_surface_flag (surface, f, sizeof (f), SDL_HWPALETTE); append_sdl_surface_flag (surface, f, sizeof (f), SDL_DOUBLEBUF); append_sdl_surface_flag (surface, f, sizeof (f), SDL_FULLSCREEN); append_sdl_surface_flag (surface, f, sizeof (f), SDL_OPENGL); append_sdl_surface_flag (surface, f, sizeof (f), SDL_RESIZABLE); append_sdl_surface_flag (surface, f, sizeof (f), SDL_NOFRAME); append_sdl_surface_flag (surface, f, sizeof (f), SDL_HWACCEL); append_sdl_surface_flag (surface, f, sizeof (f), SDL_SRCCOLORKEY); append_sdl_surface_flag (surface, f, sizeof (f), SDL_RLEACCELOK); append_sdl_surface_flag (surface, f, sizeof (f), SDL_RLEACCEL); append_sdl_surface_flag (surface, f, sizeof (f), SDL_SRCALPHA); append_sdl_surface_flag (surface, f, sizeof (f), SDL_PREALLOC); if (f[0] == '\0') strcpy (f, " (none)"); printf (" flags :%s\n", f); } printf ("\n"); } static void output_details (void) { output_videoinfo_details (); output_surface_details ("Source Surface", src); output_surface_details ("Destination Surface", dest); } static Uint32 blit (SDL_Surface * dst, SDL_Surface * src, int x, int y) { Uint32 start = 0; SDL_Rect srcRect; SDL_Rect dstRect; srcRect.x = 0; srcRect.y = 0; dstRect.x = x; dstRect.y = y; dstRect.w = srcRect.w = src->w; /* SDL will clip as appropriate. */ dstRect.h = srcRect.h = src->h; start = SDL_GetTicks (); SDL_BlitSurface (src, &srcRect, dst, &dstRect); return (SDL_GetTicks () - start); } static void blitCentered (SDL_Surface * dst, SDL_Surface * src) { int x = (dst->w - src->w) / 2; int y = (dst->h - src->h) / 2; blit (dst, src, x, y); } static int atoi_hex (const char *str) { if (str == NULL) return 0; if (strlen (str) > 2) { int retval = 0; if ((str[0] == '0') && (str[1] == 'x')) sscanf (str + 2, "%X", &retval); return (retval); } return (atoi (str)); } static int setup_test (int argc, char **argv) { const char *dumpfile = NULL; SDL_Surface *bmp = NULL; Uint32 dstbpp = 32; Uint32 dstrmask = 0x00FF0000; Uint32 dstgmask = 0x0000FF00; Uint32 dstbmask = 0x000000FF; Uint32 dstamask = 0x00000000; Uint32 dstflags = 0; int dstw = 640; int dsth = 480; Uint32 srcbpp = 32; Uint32 srcrmask = 0x00FF0000; Uint32 srcgmask = 0x0000FF00; Uint32 srcbmask = 0x000000FF; Uint32 srcamask = 0x00000000; Uint32 srcflags = 0; int srcw = 640; int srch = 480; Uint32 origsrcalphaflags = 0; Uint32 origdstalphaflags = 0; Uint32 srcalphaflags = 0; Uint32 dstalphaflags = 0; int srcalpha = 255; int dstalpha = 255; int screenSurface = 0; int i = 0; for (i = 1; i < argc; i++) { const char *arg = argv[i]; if (strcmp (arg, "--dstbpp") == 0) dstbpp = atoi (argv[++i]); else if (strcmp (arg, "--dstrmask") == 0) dstrmask = atoi_hex (argv[++i]); else if (strcmp (arg, "--dstgmask") == 0) dstgmask = atoi_hex (argv[++i]); else if (strcmp (arg, "--dstbmask") == 0) dstbmask = atoi_hex (argv[++i]); else if (strcmp (arg, "--dstamask") == 0) dstamask = atoi_hex (argv[++i]); else if (strcmp (arg, "--dstwidth") == 0) dstw = atoi (argv[++i]); else if (strcmp (arg, "--dstheight") == 0) dsth = atoi (argv[++i]); else if (strcmp (arg, "--dsthwsurface") == 0) dstflags |= SDL_HWSURFACE; else if (strcmp (arg, "--srcbpp") == 0) srcbpp = atoi (argv[++i]); else if (strcmp (arg, "--srcrmask") == 0) srcrmask = atoi_hex (argv[++i]); else if (strcmp (arg, "--srcgmask") == 0) srcgmask = atoi_hex (argv[++i]); else if (strcmp (arg, "--srcbmask") == 0) srcbmask = atoi_hex (argv[++i]); else if (strcmp (arg, "--srcamask") == 0) srcamask = atoi_hex (argv[++i]); else if (strcmp (arg, "--srcwidth") == 0) srcw = atoi (argv[++i]); else if (strcmp (arg, "--srcheight") == 0) srch = atoi (argv[++i]); else if (strcmp (arg, "--srchwsurface") == 0) srcflags |= SDL_HWSURFACE; else if (strcmp (arg, "--seconds") == 0) testSeconds = atoi (argv[++i]); else if (strcmp (arg, "--screen") == 0) screenSurface = 1; else if (strcmp (arg, "--dumpfile") == 0) dumpfile = argv[++i]; /* !!! FIXME: set colorkey. */ else if (0) { /* !!! FIXME: we handle some commandlines elsewhere now */ fprintf (stderr, "Unknown commandline option: %s\n", arg); return (0); } } if (SDL_Init (SDL_INIT_VIDEO) == -1) { fprintf (stderr, "SDL_Init failed: %s\n", SDL_GetError ()); return (0); } bmp = SDL_LoadBMP ("sample.bmp"); if (bmp == NULL) { fprintf (stderr, "SDL_LoadBMP failed: %s\n", SDL_GetError ()); SDL_Quit (); return (0); } if ((dstflags & SDL_HWSURFACE) == 0) dstflags |= SDL_SWSURFACE; if ((srcflags & SDL_HWSURFACE) == 0) srcflags |= SDL_SWSURFACE; if (screenSurface) dest = SDL_SetVideoMode (dstw, dsth, dstbpp, dstflags); else { dest = SDL_CreateRGBSurface (dstflags, dstw, dsth, dstbpp, dstrmask, dstgmask, dstbmask, dstamask); } if (dest == NULL) { fprintf (stderr, "dest surface creation failed: %s\n", SDL_GetError ()); SDL_Quit (); return (0); } src = SDL_CreateRGBSurface (srcflags, srcw, srch, srcbpp, srcrmask, srcgmask, srcbmask, srcamask); if (src == NULL) { fprintf (stderr, "src surface creation failed: %s\n", SDL_GetError ()); SDL_Quit (); return (0); } /* handle alpha settings... */ srcalphaflags = (src->flags & SDL_SRCALPHA) | (src->flags & SDL_RLEACCEL); dstalphaflags = (dest->flags & SDL_SRCALPHA) | (dest->flags & SDL_RLEACCEL); origsrcalphaflags = srcalphaflags; origdstalphaflags = dstalphaflags; srcalpha = src->format->alpha; dstalpha = dest->format->alpha; for (i = 1; i < argc; i++) { const char *arg = argv[i]; if (strcmp (arg, "--srcalpha") == 0) srcalpha = atoi (argv[++i]); else if (strcmp (arg, "--dstalpha") == 0) dstalpha = atoi (argv[++i]); else if (strcmp (arg, "--srcsrcalpha") == 0) srcalphaflags |= SDL_SRCALPHA; else if (strcmp (arg, "--srcnosrcalpha") == 0) srcalphaflags &= ~SDL_SRCALPHA; else if (strcmp (arg, "--srcrleaccel") == 0) srcalphaflags |= SDL_RLEACCEL; else if (strcmp (arg, "--srcnorleaccel") == 0) srcalphaflags &= ~SDL_RLEACCEL; else if (strcmp (arg, "--dstsrcalpha") == 0) dstalphaflags |= SDL_SRCALPHA; else if (strcmp (arg, "--dstnosrcalpha") == 0) dstalphaflags &= ~SDL_SRCALPHA; else if (strcmp (arg, "--dstrleaccel") == 0) dstalphaflags |= SDL_RLEACCEL; else if (strcmp (arg, "--dstnorleaccel") == 0) dstalphaflags &= ~SDL_RLEACCEL; } if ((dstalphaflags != origdstalphaflags) || (dstalpha != dest->format->alpha)) SDL_SetAlpha (dest, dstalphaflags, (Uint8) dstalpha); if ((srcalphaflags != origsrcalphaflags) || (srcalpha != src->format->alpha)) SDL_SetAlpha (src, srcalphaflags, (Uint8) srcalpha); /* set some sane defaults so we can see if the blit code is broken... */ SDL_FillRect (dest, NULL, SDL_MapRGB (dest->format, 0, 0, 0)); SDL_FillRect (src, NULL, SDL_MapRGB (src->format, 0, 0, 0)); blitCentered (src, bmp); SDL_FreeSurface (bmp); if (dumpfile) SDL_SaveBMP (src, dumpfile); /* make sure initial convert is sane. */ output_details (); return (1); } static void test_blit_speed (void) { Uint32 clearColor = SDL_MapRGB (dest->format, 0, 0, 0); Uint32 iterations = 0; Uint32 elasped = 0; Uint32 end = 0; Uint32 now = 0; Uint32 last = 0; int testms = testSeconds * 1000; int wmax = (dest->w - src->w); int hmax = (dest->h - src->h); int isScreen = (SDL_GetVideoSurface () == dest); SDL_Event event; printf ("Testing blit speed for %d seconds...\n", testSeconds); now = SDL_GetTicks (); end = now + testms; do { /* pump the event queue occasionally to keep OS happy... */ if (now - last > 1000) { last = now; while (SDL_PollEvent (&event)) { /* no-op. */ } } iterations++; elasped += blit (dest, src, randRange (0, wmax), randRange (0, hmax)); if (isScreen) { SDL_Flip (dest); /* show it! */ SDL_FillRect (dest, NULL, clearColor); /* blank it for next time! */ } now = SDL_GetTicks (); } while (now < end); printf ("Non-blitting crap accounted for %d percent of this run.\n", percent (testms - elasped, testms)); printf ("%d blits took %d ms (%d fps).\n", (int) iterations, (int) elasped, (int) (((float) iterations) / (((float) elasped) / 1000.0f))); } int main (int argc, char **argv) { int initialized = setup_test (argc, argv); if (initialized) { test_blit_speed (); SDL_Quit (); } return (!initialized); } /* end of testblitspeed.c ... */