e14743d1 |
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 | |