1 /* An example demonstrating different blending modes.
2  */
3 #include <allegro5/allegro.h>
4 #include <allegro5/allegro_font.h>
5 #include <allegro5/allegro_image.h>
6 #include <allegro5/allegro_color.h>
7 #include <stdio.h>
8 #include <stdarg.h>
9 #include <math.h>
10 
11 #include "common.c"
12 
13 struct Example
14 {
15    ALLEGRO_BITMAP *pattern;
16    ALLEGRO_FONT *font;
17    ALLEGRO_EVENT_QUEUE *queue;
18    ALLEGRO_COLOR background, text, white;
19 
20    double timer[4], counter[4];
21    int FPS;
22    float text_x, text_y;
23 } ex;
24 
example_bitmap(int w,int h)25 static ALLEGRO_BITMAP *example_bitmap(int w, int h)
26 {
27    int i, j;
28    float mx = w * 0.5;
29    float my = h * 0.5;
30    ALLEGRO_STATE state;
31    ALLEGRO_BITMAP *pattern = al_create_bitmap(w, h);
32    al_store_state(&state, ALLEGRO_STATE_TARGET_BITMAP);
33    al_set_target_bitmap(pattern);
34    al_lock_bitmap(pattern, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_WRITEONLY);
35    for (i = 0; i < w; i++) {
36       for (j = 0; j < h; j++) {
37          float a = atan2(i - mx, j - my);
38          float d = sqrt(pow(i - mx, 2) + pow(j - my, 2));
39          float sat = pow(1.0 - 1 / (1 + d * 0.1), 5);
40          float hue = 3 * a * 180 / ALLEGRO_PI;
41          hue = (hue / 360 - floorf(hue / 360)) * 360;
42          al_put_pixel(i, j, al_color_hsv(hue, sat, 1));
43       }
44    }
45    al_put_pixel(0, 0, al_map_rgb(0, 0, 0));
46    al_unlock_bitmap(pattern);
47    al_restore_state(&state);
48    return pattern;
49 }
50 
set_xy(float x,float y)51 static void set_xy(float x, float y)
52 {
53     ex.text_x = x;
54     ex.text_y = y;
55 }
56 
get_xy(float * x,float * y)57 static void get_xy(float *x, float *y)
58 {
59     *x = ex.text_x;
60     *y = ex.text_y;
61 }
62 
print(char const * format,...)63 static void print(char const *format, ...)
64 {
65    va_list list;
66    char message[1024];
67    int th = al_get_font_line_height(ex.font);
68    va_start(list, format);
69    vsnprintf(message, sizeof message, format, list);
70    va_end(list);
71    al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
72    al_draw_textf(ex.font, ex.text, ex.text_x, ex.text_y, 0, "%s", message);
73    ex.text_y += th;
74 }
75 
start_timer(int i)76 static void start_timer(int i)
77 {
78    ex.timer[i] -= al_get_time();
79    ex.counter[i]++;
80 }
81 
stop_timer(int i)82 static void stop_timer(int i)
83 {
84     ex.timer[i] += al_get_time();
85 }
86 
get_fps(int i)87 static double get_fps(int i)
88 {
89    if (ex.timer[i] == 0)
90       return 0;
91    return ex.counter[i] / ex.timer[i];
92 }
93 
draw(void)94 static void draw(void)
95 {
96    float x, y;
97    int iw = al_get_bitmap_width(ex.pattern);
98    int ih = al_get_bitmap_height(ex.pattern);
99    ALLEGRO_BITMAP *screen, *temp;
100    ALLEGRO_LOCKED_REGION *lock;
101    void *data;
102    int size, i, format;
103 
104    al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
105 
106    al_clear_to_color(ex.background);
107 
108    screen = al_get_target_bitmap();
109 
110    set_xy(8, 8);
111 
112    /* Test 1. */
113    /* Disabled: drawing to same bitmap is not supported. */
114    /*
115    print("Screen -> Screen (%.1f fps)", get_fps(0));
116    get_xy(&x, &y);
117    al_draw_bitmap(ex.pattern, x, y, 0);
118 
119    start_timer(0);
120    al_draw_bitmap_region(screen, x, y, iw, ih, x + 8 + iw, y, 0);
121    stop_timer(0);
122    set_xy(x, y + ih);
123    */
124 
125    /* Test 2. */
126    print("Screen -> Bitmap -> Screen (%.1f fps)", get_fps(1));
127    get_xy(&x, &y);
128    al_draw_bitmap(ex.pattern, x, y, 0);
129 
130    temp = al_create_bitmap(iw, ih);
131    al_set_target_bitmap(temp);
132    al_clear_to_color(al_map_rgba_f(1, 0, 0, 1));
133    start_timer(1);
134    al_draw_bitmap_region(screen, x, y, iw, ih, 0, 0, 0);
135 
136    al_set_target_bitmap(screen);
137    al_draw_bitmap(temp, x + 8 + iw, y, 0);
138    stop_timer(1);
139    set_xy(x, y + ih);
140 
141    al_destroy_bitmap(temp);
142 
143    /* Test 3. */
144    print("Screen -> Memory -> Screen (%.1f fps)", get_fps(2));
145    get_xy(&x, &y);
146    al_draw_bitmap(ex.pattern, x, y, 0);
147 
148    al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
149    temp = al_create_bitmap(iw, ih);
150    al_set_target_bitmap(temp);
151    al_clear_to_color(al_map_rgba_f(1, 0, 0, 1));
152    start_timer(2);
153    al_draw_bitmap_region(screen, x, y, iw, ih, 0, 0, 0);
154 
155    al_set_target_bitmap(screen);
156    al_draw_bitmap(temp, x + 8 + iw, y, 0);
157    stop_timer(2);
158    set_xy(x, y + ih);
159 
160    al_destroy_bitmap(temp);
161    al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP);
162 
163    /* Test 4. */
164    print("Screen -> Locked -> Screen (%.1f fps)", get_fps(3));
165    get_xy(&x, &y);
166    al_draw_bitmap(ex.pattern, x, y, 0);
167 
168    start_timer(3);
169    lock = al_lock_bitmap_region(screen, x, y, iw, ih,
170       ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY);
171    format = lock->format;
172    size = lock->pixel_size;
173    data = malloc(size * iw * ih);
174    for (i = 0; i < ih; i++)
175       memcpy((char*)data + i * size * iw,
176          (char*)lock->data + i * lock->pitch, size * iw);
177    al_unlock_bitmap(screen);
178 
179    lock = al_lock_bitmap_region(screen, x + 8 + iw, y, iw, ih, format,
180       ALLEGRO_LOCK_WRITEONLY);
181    for (i = 0; i < ih; i++)
182       memcpy((char*)lock->data + i * lock->pitch,
183          (char*)data + i * size * iw, size * iw);
184    al_unlock_bitmap(screen);
185    free(data);
186    stop_timer(3);
187    set_xy(x, y + ih);
188 
189 }
190 
tick(void)191 static void tick(void)
192 {
193    draw();
194    al_flip_display();
195 }
196 
run(void)197 static void run(void)
198 {
199    ALLEGRO_EVENT event;
200    bool need_draw = true;
201 
202    while (1) {
203       if (need_draw && al_is_event_queue_empty(ex.queue)) {
204          tick();
205          need_draw = false;
206       }
207 
208       al_wait_for_event(ex.queue, &event);
209 
210       switch (event.type) {
211          case ALLEGRO_EVENT_DISPLAY_CLOSE:
212             return;
213 
214          case ALLEGRO_EVENT_KEY_DOWN:
215             if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
216                return;
217             break;
218 
219          case ALLEGRO_EVENT_TIMER:
220             need_draw = true;
221             break;
222       }
223    }
224 }
225 
init(void)226 static void init(void)
227 {
228    ex.FPS = 60;
229 
230    ex.font = al_load_font("data/fixed_font.tga", 0, 0);
231    if (!ex.font) {
232       abort_example("data/fixed_font.tga not found\n");
233    }
234    ex.background = al_color_name("beige");
235    ex.text = al_color_name("black");
236    ex.white = al_color_name("white");
237    ex.pattern = example_bitmap(100, 100);
238 }
239 
main(int argc,char ** argv)240 int main(int argc, char **argv)
241 {
242    ALLEGRO_DISPLAY *display;
243    ALLEGRO_TIMER *timer;
244 
245    (void)argc;
246    (void)argv;
247 
248    if (!al_init()) {
249       abort_example("Could not init Allegro.\n");
250    }
251 
252    al_install_keyboard();
253    al_install_mouse();
254    al_init_image_addon();
255    al_init_font_addon();
256    init_platform_specific();
257 
258    display = al_create_display(640, 480);
259    if (!display) {
260       abort_example("Error creating display\n");
261    }
262 
263    init();
264 
265    timer = al_create_timer(1.0 / ex.FPS);
266 
267    ex.queue = al_create_event_queue();
268    al_register_event_source(ex.queue, al_get_keyboard_event_source());
269    al_register_event_source(ex.queue, al_get_mouse_event_source());
270    al_register_event_source(ex.queue, al_get_display_event_source(display));
271    al_register_event_source(ex.queue, al_get_timer_event_source(timer));
272 
273    al_start_timer(timer);
274    run();
275 
276    al_destroy_event_queue(ex.queue);
277 
278    return 0;
279 }
280