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