1 /*
2  *    Benchmark for memory blenders.
3  */
4 
5 #include <stdio.h>
6 #include <allegro5/allegro.h>
7 #include <allegro5/allegro_image.h>
8 #include <allegro5/allegro_primitives.h>
9 #include <time.h>
10 
11 #include "common.c"
12 
13 /* Do a few un-timed runs to switch CPU to performance mode and cache
14  * data and so on - seems to make the results more stable here.
15  * Also used to guess the number of timed iterations.
16  */
17 #define WARMUP 100
18 /* How many seconds the timing should approximately take - a fixed
19  * number of iterations is not enough on very fast systems but takes
20  * too long on slow systems.
21  */
22 #define TEST_TIME 5.0
23 
24 enum Mode {
25    ALL,
26    PLAIN_BLIT,
27    SCALED_BLIT,
28    ROTATE_BLIT
29 };
30 
31 static char const *names[] = {
32    "", "Plain blit", "Scaled blit", "Rotated blit"
33 };
34 
35 ALLEGRO_DISPLAY *display;
36 
step(enum Mode mode,ALLEGRO_BITMAP * b2)37 static void step(enum Mode mode, ALLEGRO_BITMAP *b2)
38 {
39    switch (mode) {
40       case ALL: break;
41       case PLAIN_BLIT:
42          al_draw_bitmap(b2, 0, 0, 0);
43          break;
44       case SCALED_BLIT:
45          al_draw_scaled_bitmap(b2, 0, 0, 320, 200, 0, 0, 640, 480, 0);
46          break;
47       case ROTATE_BLIT:
48          al_draw_scaled_rotated_bitmap(b2, 10, 10, 10, 10, 2.0, 2.0,
49             ALLEGRO_PI/30, 0);
50          break;
51    }
52 }
53 
54 /* al_get_current_time() measures wallclock time - but for the benchmark
55  * result we prefer CPU time so clock() is better.
56  */
current_clock(void)57 static double current_clock(void)
58 {
59    clock_t c = clock();
60    return (double)c / CLOCKS_PER_SEC;
61 }
62 
do_test(enum Mode mode)63 static bool do_test(enum Mode mode)
64 {
65    ALLEGRO_STATE state;
66    ALLEGRO_BITMAP *b1;
67    ALLEGRO_BITMAP *b2;
68    int REPEAT;
69    double t0, t1;
70    int i;
71 
72    al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
73 
74    b1 = al_load_bitmap("data/mysha.pcx");
75    if (!b1) {
76       abort_example("Error loading data/mysha.pcx\n");
77       return false;
78    }
79 
80    b2 = al_load_bitmap("data/allegro.pcx");
81    if (!b2) {
82       abort_example("Error loading data/mysha.pcx\n");
83       return false;
84    }
85 
86    al_set_target_bitmap(b1);
87    al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
88    step(mode, b2);
89 
90    /* Display the blended bitmap to the screen so we can see something. */
91    al_store_state(&state, ALLEGRO_STATE_ALL);
92    al_set_target_backbuffer(display);
93    al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
94    al_draw_bitmap(b1, 0, 0, 0);
95    al_flip_display();
96    al_restore_state(&state);
97 
98    log_printf("Benchmark: %s\n", names[mode]);
99    log_printf("Please wait...\n");
100 
101    /* Do warmup run and estimate required runs for real test. */
102    t0 = current_clock();
103    for (i = 0; i < WARMUP; i++) {
104       step(mode, b2);
105    }
106    t1 = current_clock();
107    REPEAT = TEST_TIME * 100 / (t1 - t0);
108 
109    /* Do the real test. */
110    t0 = current_clock();
111    for (i = 0; i < REPEAT; i++) {
112       step(mode, b2);
113    }
114    t1 = current_clock();
115 
116    log_printf("Time = %g s, %d steps\n",
117       t1 - t0, REPEAT);
118    log_printf("%s: %g FPS\n", names[mode], REPEAT / (t1 - t0));
119    log_printf("Done\n");
120 
121    al_destroy_bitmap(b1);
122    al_destroy_bitmap(b2);
123 
124    return true;
125 }
126 
main(int argc,char ** argv)127 int main(int argc, char **argv)
128 {
129    enum Mode mode = ALL;
130    int i;
131 
132    if (argc > 1) {
133       i = strtol(argv[1], NULL, 10);
134       switch (i) {
135          case 0:
136             mode = PLAIN_BLIT;
137             break;
138          case 1:
139             mode = SCALED_BLIT;
140             break;
141          case 2:
142             mode = ROTATE_BLIT;
143             break;
144       }
145    }
146 
147    if (!al_init()) {
148       abort_example("Could not init Allegro\n");
149    }
150 
151    open_log();
152 
153    al_init_image_addon();
154    al_init_primitives_addon();
155    init_platform_specific();
156 
157    display = al_create_display(640, 480);
158    if (!display) {
159       abort_example("Error creating display\n");
160    }
161 
162    if (mode == ALL) {
163       for (mode = PLAIN_BLIT; mode <= ROTATE_BLIT; mode++) {
164          do_test(mode);
165       }
166    }
167    else {
168       do_test(mode);
169    }
170 
171    al_destroy_display(display);
172 
173    close_log(true);
174 
175    return 0;
176 }
177 
178 /* vim: set sts=3 sw=3 et: */
179